8000 chore: preps by mertmit · Pull Request #9994 · nocodb/nocodb · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

chore: preps #9994

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 9, 2024
Merged

chore: preps #9994

merged 2 commits into from
Dec 9, 2024

Conversation

mertmit
Copy link
Member
@mertmit mertmit commented Dec 7, 2024

Change Summary

Provide summary of changes with issue number if any.

Change type

  • chore: (updating grunt tasks etc; no production code change)

@dosubot dosubot bot added the size:XL This PR changes 500-999 lines, ignoring generated files. label Dec 7, 2024
Copy link
Contributor
coderabbitai bot commented Dec 7, 2024

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 ast-grep (0.30.1)
packages/nc-gui/components/ai/PromptWithFields.vue

An unexpected error occurred while running ast-grep.

📝 Walkthrough

Walkthrough

This pull request introduces significant enhancements across multiple components in the CodeRabbit application. Key modifications include the addition of new properties for managing read-only states and AI functionalities, improved error handling, and refined user interaction features. Components such as PromptWithFields.vue, Settings.vue, and various Smartsheet-related files have been updated to incorporate these changes, which enhance usability and maintainability. Additionally, new utility functions and types have been introduced to support AI-related features, alongside adjustments to existing logic for better integration of these functionalities.

Changes

File Path Change Summary
packages/nc-gui/components/ai/PromptWithFields.vue Added readOnly prop for editable state; refined mention handling; introduced tooltip feature for mention tags; adjusted button and prompt field styling.
packages/nc-gui/components/ai/Settings.vue Added isEditColumn prop; updated availableModels type; modified template and styles for select components.
packages/nc-gui/components/cell/AI.vue Injected isUIAllowed and isPublic; simplified computed property for AI integration; updated generate function and button disable logic.
packages/nc-gui/components/cell/TextArea.vue Introduced meta dependency; replaced aiLoading with isAiGenerating; refined AI-related warning logic.
packages/nc-gui/components/cell/attachment/index.vue Renamed icon component; refined file attachment handling; updated button styling.
packages/nc-gui/components/general/IntegrationIcon.vue Changed size prop to optional; default set to 'sm'.
packages/nc-gui/components/general/Loader.vue Added GeneralLoaderProps interface; updated props definition.
packages/nc-gui/components/nc/Button.vue Added loaderSize prop; updated template bindings for loader size.
packages/nc-gui/components/nc/List/RecordItem.vue Updated logic for handling row data; improved attachment handling with error checks.
packages/nc-gui/components/nc/Switch.vue Updated template for disabled state styling.
packages/nc-gui/components/smartsheet/Cell.vue Added cellType computed property for rendering logic.
packages/nc-gui/components/smartsheet/Gallery.vue Updated context menu icon; improved attachment error handling.
packages/nc-gui/components/smartsheet/Kanban.vue Enhanced context menu functionality; refined stack movement logic.
packages/nc-gui/components/smartsheet/PlainCell.vue Updated handling for AI prompt columns; added AI-related imports.
packages/nc-gui/components/smartsheet/column/AiButtonOptions.vue Added is-edit-column prop; refined submit button logic.
packages/nc-gui/components/smartsheet/column/ButtonOptions.vue Updated AI button type handling logic.
packages/nc-gui/components/smartsheet/column/EditOrAdd.vue Enhanced AI-related functionalities; updated rendering logic.
packages/nc-gui/components/smartsheet/column/LongTextOptions.vue Updated prop and emitted event for modelValue; added reactive properties for AI generation.
packages/nc-gui/components/smartsheet/column/UITypesOptionsWithSearch.vue Updated filtering logic for AI-related options.
packages/nc-gui/components/smartsheet/details/Fields.vue Enhanced field management with AI suggestions; added delay for copy field URL.
packages/nc-gui/components/smartsheet/expanded-form/index.vue Improved form handling and user interactions; added delay for copy record URL.
packages/nc-gui/components/smartsheet/grid/GroupByTable.vue Updated Table component bindings for selection state.
packages/nc-gui/components/smartsheet/grid/InfiniteTable.vue Enhanced AI-related functionalities in row updates.
packages/nc-gui/components/smartsheet/grid/Table.vue Updated AI-related logic for selected columns.
packages/nc-gui/components/smartsheet/header/Cell.vue Enhanced column type determination logic.
packages/nc-gui/components/smartsheet/header/CellIcon.ts Updated icon rendering logic for AI columns.
packages/nc-gui/components/smartsheet/header/Menu.vue Added AI integration checks in column validity.
packages/nc-gui/components/smartsheet/header/VirtualCell.vue Updated column type handling for AI buttons.
packages/nc-gui/components/smartsheet/toolbar/ViewActionMenu.vue Enhanced view locking and user interactions.
packages/nc-gui/components/virtual-cell/Button.vue Updated button styling; refined action handling logic.
packages/nc-gui/components/virtual-cell/HasMany.vue Updated dialog handling logic; refined icon styling.
packages/nc-gui/components/virtual-cell/ManyToMany.vue Enhanced dialog visibility checks; updated icon handling.
packages/nc-gui/components/virtual-cell/components/ListItem.vue Replaced icon component; improved error handling.
packages/nc-gui/components/workspace/integrations/ConnectionsTab.vue Removed AI integration loading logic.
packages/nc-gui/components/workspace/integrations/IntegrationsTab.vue Added loadDynamicIntegrations method for initialization.
packages/nc-gui/components/workspace/integrations/forms/EditOrAddCommon.vue Updated import syntax for types; removed AI integration loading on submit.
packages/nc-gui/components/workspace/integrations/forms/EditOrAddDatabase.vue Enhanced UI and validation for database connection form.
packages/nc-gui/components/workspace/project/AiCreateProject.vue Updated schema prediction logic with new prompt structure.
packages/nc-gui/composables/useColumnCreateStore.ts Enhanced AI-related functionality in column creation.
packages/nc-gui/composables/useData.ts Updated row update logic for AI prompt columns.
packages/nc-gui/composables/useInfiniteData.ts Enhanced row update logic with AI checks.
packages/nc-gui/composables/useIntegrationsStore.ts Enhanced integration management with AI handling.
packages/nc-gui/composables/useMultiSelect/index.ts Updated long text value handling for AI processing.
packages/nc-gui/composables/useNocoAi.ts Updated AI integrations logic; added new computed property.
packages/nc-gui/helpers/parsers/parserHelpers.ts Enhanced unique column name generation for AI types.
packages/nc-gui/helpers/tiptapExtensions/mention/FieldList.vue Improved keyboard navigation and visual presentation.
packages/nc-gui/nuxt.config.ts Added new dependencies for enhanced functionality.
packages/nocodb-sdk/src/lib/Api.ts Simplified bulkDeleteAll method for row deletion.
packages/nocodb-sdk/src/lib/UITypes.ts Added new UI types and functionality for AI columns.
packages/nocodb-sdk/src/lib/globals.ts Updated metadata constants for AI integration.
packages/nocodb-sdk/src/lib/helperFunctions.ts Added JSON parsing and stringifying helper functions.
packages/nocodb-sdk/src/lib/index.ts Exported new UI type functions.
packages/nocodb/src/db/BaseModelSqlv2.ts Enhanced handling for AI prompt columns in data preparation.
packages/nocodb/src/db/conditionV2.ts Updated SQL query handling for AI prompt columns.
packages/nocodb/src/db/formulav2/formulaQueryBuilderv2.ts Enhanced SQL query handling for long text types.
packages/nocodb/src/db/sortV2.ts Updated sorting logic for AI prompt columns.
packages/nocodb/src/meta/migrations/XcMigrationSourcev2.ts Added new migration for AI prompts.
packages/nocodb/src/meta/migrations/v2/nc_069_ai_prompt.ts Introduced migration for managing AI prompt tables.
packages/nocodb/src/models/AIColumn.ts Added new AIColumn class for managing AI-related data.
packages/nocodb/src/models/Column.ts Enhanced column management for AI types.
packages/nocodb/src/models/Integration.ts Updated integration management logic for AI columns.
packages/nocodb/src/models/LongTextColumn.ts Introduced LongTextColumn class for managing long text data.
packages/nocodb/src/models/index.ts Exported new AI and LongText column models.
packages/nocodb/src/modules/jobs/jobs/export-import/duplicate.processor.ts Updated duplication logic to handle AI prompt columns.
packages/nocodb/src/modules/jobs/jobs/export-import/export.service.ts Enhanced export functionality for long text types.
packages/nocodb/src/modules/jobs/jobs/export-import/import.service.ts Refined import logic for AI prompt columns.
packages/nocodb/src/services/columns.service.ts Enhanced column update logic for AI prompt handling.
packages/nocodb/src/utils/dataConversion.ts Added functions for converting AI record types.
packages/nocodb/src/utils/globals.ts Updated metadata constants for AI integration.

Possibly related PRs

Suggested reviewers

  • dstala

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor
github-actions bot commented Dec 7, 2024

Uffizzi Preview deployment-58926 was deleted.

Copy link
Contributor
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 14

🧹 Outside diff range and nitpick comments (52)
packages/nc-gui/components/nc/Switch.vue (1)

45-47: Consider enhancing accessibility for disabled state.

While the visual feedback is good, consider adding ARIA attributes to improve screen reader support.

Add aria-disabled="true" when the switch is disabled:

  <span
    v-if="placement === 'right' && $slots.default"
    class="pr-2"
+   :aria-disabled="disabled"
    :class="[
      contentWrapperClass,
      {
        'cursor-not-allowed opacity-60': disabled,
        'cursor-pointer': !disabled,
      },
    ]"
    @click="onChange(!checked, true)"
  >

Apply the same change to the left-placed label span as well.

Also applies to: 72-74

packages/nc-gui/components/nc/Button.vue (1)

4-4: Consider using path alias for type import.

The relative import path could be replaced with a path alias for better maintainability.

-import type { GeneralLoaderProps } from '../general/Loader.vue'
+import type { GeneralLoaderProps } from '~/components/general/Loader.vue'
packages/nocodb/src/modules/jobs/jobs/export-import/duplicate.processor.ts (1)

443-443: LGTM: Added protection for AI prompt columns

The additional check prevents updating default values for AI prompt columns, which is a good defensive measure. Consider adding a comment explaining why AI prompt columns should not have their default values updated, to help future maintainers understand the reasoning.

-    if (!isVirtualCol(destColumn) && !isAIPromptCol(destColumn)) {
+    // Skip updating default values for virtual and AI prompt columns as they are computed/generated
+    if (!isVirtualCol(destColumn) && !isAIPromptCol(destColumn)) {
packages/nc-gui/components/general/IntegrationIcon.vue (1)

Line range hint 5-9: Consider adding JSDoc comments for better documentation.

Since this component is part of a UI library, it would be helpful to add JSDoc comments explaining the size options and their visual impact.

+/**
+ * @prop {('sx'|'sm'|'md'|'lg'|'xl'|'xxl')} [size='sm'] - Controls the icon size
+ * - 'sx': Extra small (14px)
+ * - 'sm': Small (16px)
+ * - 'md': Medium (20px)
+ * - 'lg': Large (24px)
+ * - 'xl': Extra large (28px)
+ * - 'xxl': Extra extra large (32px)
+ */
 defineProps<{
   type: string
   size?: 'sx' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl'
 }>()
packages/nc-gui/components/smartsheet/header/VirtualCell.vue (2)

133-136: Consider adding documentation for AI button handling

The integration of AI button type handling is clean and follows the component's patterns. However, adding documentation would help explain:

  • The precedence of AI button type over other types
  • The expected behavior and use cases
  • The relationship with other column types

Consider adding a comment above the condition:

+  // AI button type takes precedence over other column types
+  // to ensure consistent handling of AI-specific functionality
   if (isAiButton(column.value)) {
     return UITypesName.AIButton
   }

133-136: Enhance type safety for AI button handling

The current implementation could benefit from improved type safety and error handling.

Consider this enhanced implementation:

-  if (isAiButton(column.value)) {
+  try {
+    if (column.value && isAiButton(column.value)) {
+      return UITypesName.AIButton
+    }
+  } catch (e) {
+    console.warn('Error checking AI button type:', e)
+  }
packages/nocodb/src/utils/dataConversion.ts (2)

15-69: Refactor database-specific SQL queries to reduce code duplication

The if-else blocks for handling different database types in the convertAIRecordTypeToValue function contain similar logic with variations in SQL syntax. Refactoring this code to abstract common functionality can improve maintainability and reduce duplication.

Consider creating a helper function that generates the appropriate SQL query and parameters based on the source.type. This approach centralizes the SQL query generation and makes it easier to manage differences between database systems.


89-149: Refactor duplicated logic in convertValueToAIRecordType function

Similar to the previous function, the if-else blocks in convertValueToAIRecordType repeat logic across different database types with minor variations in SQL syntax. Abstracting common code into a helper function can enhance readability and ease future maintenance.

Implementing a utility function to construct the SQL queries and parameter arrays based on the source.type can reduce code repetition and simplify the function structure.

packages/nc-gui/nuxt.config.ts (1)

Line range hint 229-258: Consider dependency management improvements

The new dependencies are added to the optimizeDeps.include array for pre-bundling. Consider the following improvements:

  1. Add version constraints for better dependency management
  2. Document the purpose of these dependencies in comments
  3. Consider moving rarely used dependencies to dynamic imports for better initial load performance

Example improvement:

optimizeDeps: {
  include: [
    // Core editor dependencies
    '@tiptap/core',
    ...
-   'crossoriginworker',
+   // Worker for cross-origin communication
+   'crossoriginworker@^1.0.0',
    ...
-   'monaco-editor/esm/vs/basic-languages/javascript/javascript',
+   // Monaco editor JavaScript language support
+   'monaco-editor/esm/vs/basic-languages/javascript/javascript@^0.34.0',
    ...
-   'vue-barcode-reader',
+   // Barcode scanning functionality
+   'vue-barcode-reader@^1.0.0',
    ...
  ],
}
packages/nc-gui/components/virtual-cell/components/ListItem.vue (3)

Line range hint 39-51: Consider enhancing error handling for attachments.

The current error handling silently returns an empty array when JSON parsing fails. Consider logging the error or providing feedback to help with debugging.

 const attachments: ComputedRef<Attachment[]> = computed(() => {
   try {
     if (props.attachment && row.value[props.attachment.title]) {
       return typeof row.value[props.attachment.title] === 'string'
         ? JSON.parse(row.value[props.attachment.title])
         : row.value[props.attachment.title]
     }
     return []
   } catch (e) {
+    console.warn(`Failed to parse attachments: ${e.message}`)
     return []
   }
 })

Line range hint 82-89: Enhance keyboard navigation for better accessibility.

The component supports basic keyboard navigation with tabindex, but could be improved by adding keyboard shortcuts for common actions like expand and link/unlink.

Consider adding keyboard event handlers:

 <a-card
   tabindex="0"
   class="nc-list-item !outline-none transition-all relative group-hover:bg-gray-50 cursor-auto"
+  @keydown.enter="$emit('expand', row)"
+  @keydown.space.prevent="$emit('expand', row)"
   :class="{
     '!bg-white': isLoading,
     '!hover:bg-white': readOnly,
   }"

Line range hint 90-161: Consider performance optimizations for large lists.

The component renders multiple fields and attachments which could impact performance with large datasets. Consider implementing:

  1. Virtual scrolling for large lists of fields
  2. Lazy loading for the attachment carousel
  3. Memoization of expensive computations

Example optimization for fields rendering:

-<div v-for="field in fields" :key="field.id" class="sm:(w-1/3 max-w-1/3 overflow-hidden)">
+<div v-for="field in visibleFields" :key="field.id" class="sm:(w-1/3 max-w-1/3 overflow-hidden)">

Add a computed property to manage visible fields:

const visibleFields = computed(() => {
  // Implement windowing logic here
  return props.fields.slice(0, 10) // Show first 10 fields initially
})
packages/nc-gui/helpers/tiptapExtensions/mention/FieldList.vue (2)

Line range hint 89-94: Enhance error handling in selectItem method

While the null check is good, consider these improvements:

  1. Add try-catch around the command execution
  2. Consider using a unique identifier instead of title as the id
  3. Add type checking for item.title
 selectItem(index, _e) {
   const item = this.items[index]

   if (item) {
+    try {
+      if (typeof item.title !== 'string') {
+        console.warn('Invalid item title type:', typeof item.title)
+        return
+      }
       this.command({
         id: item.title,
       })
+    } catch (error) {
+      console.error('Failed to execute command:', error)
+    }
   }
 }

102-122: Consider adding accessibility improvements

The component could benefit from these accessibility enhancements:

  1. Add role="listbox" to the container div
  2. Add role="option" and aria-selected to individual items
  3. Add aria-activedescendant to indicate the selected item
 <div
   class="w-64 bg-white scroll-smooth nc-mention-list nc-scrollbar-thin border-1 border-gray-200 rounded-lg max-h-64 !py-2 px-2 shadow-lg"
+  role="listbox"
+  :aria-activedescendant="'item-' + selectedIndex"
   @mousedown.stop
 >
   <template v-if="items.length">
     <div
       v-for="(item, index) in items"
       :key="index"
       :class="{ 'is-selected': index === selectedIndex }"
+      :id="'item-' + index"
+      role="option"
+      :aria-selected="index === selectedIndex"
       class="py-2 flex hover:bg-gray-100 rounded-md transition-all cursor-pointer items-center gap-2 text-gray-800 pl-4"
       @click="selectItem(index, $event)"
     >
packages/nc-gui/components/smartsheet/column/LongTextOptions.vue (1)

295-304: Simplify nested ternary operators for better readability

The nested ternary operator in lines 295-304 makes the code hard to read and maintain. Consider refactoring this logic into a computed property or method for clarity.

For example, you can create a computed property for the button label:

const generateButtonLabel = computed(() => {
  if (isAlreadyGenerated.value) {
    return generatingPreview.value ? 'Re-generating' : 'Re-generate';
  } else {
    return generatingPreview.value ? 'Generating' : 'Generate preview';
  }
});

And update the template:

- {{
-   isAlreadyGenerated
-     ? generatingPreview
-       ? 'Re-generating'
-       : 'Re-generate'
-     : generatingPreview
-     ? 'Generating'
-     : 'Generate preview'
- }}
+ {{ generateButtonLabel }}
packages/nc-gui/composables/useIntegrationsStore.ts (1)

296-296: Use optional chaining to prevent potential errors

Consider using optional chaining when accessing integrationForms[integration.subType] to handle cases where integrationForms might be undefined.

Apply this diff:

- if (!(integration.subType in integrationForms)) {
+ if (!integrationForms?.[integration.subType]) {

This change ensures that your code doesn't throw an error if integrationForms is undefined.

🧰 Tools
🪛 Biome (1.9.4)

[error] 296-296: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

packages/nc-gui/components/cell/TextArea.vue (1)

104-111: Simplify the computed property logic

The double negation !! in the computed property isAiGenerating is unnecessary since the expression already evaluates to a boolean.

Simplify the computed property by removing the double negation:

- return !!(
+ return (

This makes the code cleaner without affecting functionality.

packages/nc-gui/components/smartsheet/column/EditOrAdd.vue (1)

1098-1104: Simplify nested ternary operators in template

The nested ternary operators used for determining the icon component make the template hard to read. Consider extracting the logic into a computed property.

For example, define a computed property for the icon:

const selectOptionIcon = (uidt) => {
  if (isAiButtonSelectOption(uidt) && !isColumnTypeOpen.value) {
    return iconMap.cellAiButton;
  } else if (isAiPromptSelectOption(uidt) && !isColumnTypeOpen.value) {
    return iconMap.cellAi;
  } else {
    return getUIDTIcon(uidt);
  }
};

And update the template:

<component
- :is="
-   isAiButtonSelectOption(opt.name) && !isColumnTypeOpen
-     ? iconMap.cellAiButton
-     : isAiPromptSelectOption(opt.name) && !isColumnTypeOpen
-     ? iconMap.cellAi
-     : opt.icon
- "
+ :is="selectOptionIcon(opt.name)"
  class="nc-field-type-icon w-4 h-4"
  :class="isMetaReadOnly && !readonlyMetaAllowedTypes.includes(opt.name) ? 'text-gray-300' : 'text-gray-700'"
/>
packages/nocodb/src/db/conditionV2.ts (2)

596-613: Refactor JSON extraction logic to improve maintainability

The code between lines 596-613 contains repeated patterns for extracting the 'value' field from a JSON column based on different database clients. Consider refactoring this logic into a helper function or mapping to reduce duplication and enhance maintainability.


597-613: Ensure consistent client type checks

The checks for knex.clientType() use both === and startsWith(). For consistency and to prevent potential misclassifications, standardize the client type comparisons. Use exact matches where possible or ensure all client types are appropriately handled.

packages/nocodb/src/models/Column.ts (1)

886-927: Avoid mutation of function parameters

Within this block, the col object is passed to parseMetaProp(col);, which might mutate its properties. Modifying function parameters can lead to unintended side effects. Consider creating a copy of col before passing it to functions that might alter it.

🧰 Tools
🪛 Biome (1.9.4)

[error] 921-921: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

packages/nc-gui/components/smartsheet/details/Fields.vue (2)

1040-1043: Remove unnecessary delay in copying field ID

The delay introduced after copying the field ID is redundant because isFieldIdCopied is reset after 5 seconds elsewhere. Removing the extra delay ensures better responsiveness.

Apply this diff to remove the unnecessary delay:

  await copy(field.id!)
- await ncDelay(5000)
  isFieldIdCopied.value = true

Line range hint 855-856: Use consistent function checks for AI features

In the computed property isSelectedOnlyAI, the functions isAIPromptCol(field) and isAiButton(field) are used. Ensure that isAiButton is defined and imported as it might lead to a reference error if not properly included.

packages/nc-gui/components/smartsheet/grid/Table.vue (1)

2140-2146: Avoid unnecessary conditional rendering of expand icons

The expand icon in the table row is conditionally rendered based on expandForm. If expandForm is undefined, the div renders empty, potentially causing layout issues. Consider adding a guard clause or providing a fallback to maintain consistent UI.

packages/nocodb/src/services/columns.service.ts (3)

1578-1583: Simplify complex condition for better readability

The condition in this if statement is complex and may hinder readability and maintenance. Consider simplifying it or extracting it into a well-named boolean variable or helper function.


1601-1645: Extract common logic to avoid code duplication

The code block that substitutes column aliases with IDs in colBody.prompt_raw appears in both the columnUpdate and colu 8000 mnAdd methods. Consider extracting this logic into a shared helper function to improve maintainability and reduce code duplication.

Also applies to: 2282-2303


1607-1607: Check for existing columns before fetching

The await table.getColumns(context); call may be unnecessary if table.columns is already populated. Check if table.columns exists before making the call to improve performance.

Also applies to: 2289-2289

packages/nocodb/src/db/BaseModelSqlv2.ts (2)

8636-8654: Avoid silently swallowing exceptions in JSON parsing

In the _convertJsonType method, the empty catch blocks mean that any exceptions thrown by JSON.parse are ignored silently. This can make debugging difficult when invalid JSON data is encountered. Consider handling the errors appropriately, such as logging them or providing a fallback mechanism.

Apply this diff to handle exceptions:

- } catch {}
+ } catch (error) {
+   console.error('Failed to parse JSON:', error);
+   // You may assign a default value or handle the error as needed
+   d[col.id] = null;
+ }

10063-10104: Ensure proper handling of undefined properties

When accessing oldObj.isStale, if oldObj exists but isStale is undefined, the assignment const isStale = oldObj ? oldObj.isStale : false; would result in isStale being undefined. To prevent potential bugs, use the nullish coalescing operator to provide a default value.

Apply this diff:

- const isStale = oldObj ? oldObj.isStale : false;
+ const isStale = oldObj?.isStale ?? false;
packages/nocodb/src/meta/migrations/v2/nc_069_ai_prompt.ts (1)

5-22: Specify column constraints for data integrity

In the migration, columns are created without specifying whether they should be nullable. To ensure data integrity, consider adding .notNullable() to columns that should not accept NULL values, such as fk_workspace_id, base_id, fk_model_id, fk_column_id, and identifiers like fk_integration_id.

Apply this diff:

table.string('id', 20).primary();
- table.string('fk_workspace_id', 20);
+ table.string('fk_workspace_id', 20).notNullable();
- table.string('base_id', 20);
+ table.string('base_id', 20).notNullable();
- table.string('fk_model_id', 20);
+ table.string('fk_model_id', 20).notNullable();
- table.string('fk_column_id', 20);
+ table.string('fk_column_id', 20).notNullable();
packages/nocodb/src/models/AIColumn.ts (1)

26-26: Avoid using 'this' in static methods for clarity

Using this inside static methods can be confusing because this refers to the class, not an instance. For better readability, replace this with the class name AIColumn.

Apply this diff:

-       return this._insert(
+       return AIColumn._insert(
-       return this._update(
+       return AIColumn._update(

Also applies to: 40-40

🧰 Tools
🪛 Biome (1.9.4)

[error] 26-26: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

packages/nc-gui/utils/commonUtils.ts (1)

103-117: Consider performance optimization for large arrays

While the current implementation is correct, consider these optimizations for better performance with large arrays:

  1. Early return if query is empty
  2. Cache toLowerCase() results for repeated use
  3. Consider using Set for large arrays
 export const searchCompare = (source?: string | number | (string | number | undefined)[], query?: string): boolean => {
+  const normalizedQuery = (query || '').toLowerCase()
+  // Early return if query is empty
+  if (!normalizedQuery) return true
+
   if (ncIsArray(source)) {
     return source.some((item) => {
-      return (item || '')
-        .toString()
-        .toLowerCase()
-        .includes((query || '').toLowerCase())
+      return (item || '').toString().toLowerCase().includes(normalizedQuery)
     })
   }

-  return (source || '')
-    .toString()
-    .toLowerCase()
-    .includes((query || '').toLowerCase())
+  return (source || '').toString().toLowerCase().includes(normalizedQuery)
 }
packages/nc-gui/components/cell/AI.vue (1)

81-92: Enhance type safety in object handling

The object type checking and fallback handling is good, but could be more robust.

Consider this safer implementation:

-      if (obj && typeof obj === 'object') {
+      if (obj && typeof obj === 'object' && !Array.isArray(obj)) {
         vModel.value = obj
         setTimeout(() => {
           isAiEdited.value = false
         }, 100)
       } else {
         vModel.value = {
-          ...(ncIsObject(vModel.value) ? vModel.value : {}),
+          ...(ncIsObject(vModel.value) && !Array.isArray(vModel.value) ? vModel.value : {}),
           isStale: false,
           value: resRow[column.value.title!],
         }
packages/nocodb-sdk/src/lib/helperFunctions.ts (2)

231-237: Consider type safety improvements for parseHelper

While the error handling is good, the function could benefit from stronger typing.

Consider this enhanced implementation:

-export function parseHelper(v: any): any {
+export function parseHelper<T = any>(v: string | T): T {
   try {
-    return typeof v === 'string' ? JSON.parse(v) : v;
+    return typeof v === 'string' ? (JSON.parse(v) as T) : v;
   } catch {
     return v as T;
   }
 }

239-244: Add type guard for stringifyHelper

The function should handle non-stringifiable values more explicitly.

Consider this enhanced implementation:

-export function stringifyHelper(v: any): string {
+export function stringifyHelper(v: unknown): string {
   try {
-    return JSON.stringify(v);
+    return v === undefined ? '' : JSON.stringify(v);
   } catch {
-    return v;
+    return String(v);
   }
 }
packages/nocodb/src/db/sortV2.ts (1)

202-228: Consider adding error handling for unsupported databases.

The implementation handles sorting for AI-enabled long text columns across different databases well. However, there's no explicit handling for unsupported database types.

Consider adding an else clause to handle unsupported databases:

  } else if (knex.clientType() === 'mssql') {
    col = knex.raw(`JSON_VALUE(??, '$.value')`, [column.column_name]);
+ } else {
+   console.warn(`JSON extraction not implemented for ${knex.clientType()}`);
+   col = sanitize(column.column_name);
  }

Also, consider adding unit tests to verify the sorting behavior for each database type.

Would you like me to help create comprehensive unit tests for this functionality?

packages/nc-gui/components/ai/PromptWithFields.vue (1)

63-68: Consider simplifying the filter condition

The filter condition can be simplified for better readability.

-return (
-  props.options?.filter(
-    (o) =>
-      o.title?.toLowerCase()?.includes(query.toLowerCase()) || `${o.title?.toLowerCase()}}` === query.toLowerCase(),
-  ) ?? []
-)
+return props.options?.filter((o) => {
+  const title = o.title?.toLowerCase() ?? ''
+  const queryLower = query.toLowerCase()
+  return title.includes(queryLower) || `${title}}` === queryLower
+}) ?? []
packages/nc-gui/components/ai/Settings.vue (1)

70-72: Document the early return condition

The early return when isEditColumn is true should be documented to explain the reasoning.

+  // Skip initialization when in column edit mode as the integration
+  // and model should be preserved
   if (isEditColumn.value) {
     return
   }
packages/nc-gui/components/smartsheet/header/Cell.vue (1)

46-55: Consider extracting type checking logic

The type checking logic in columnTypeName could be extracted into a separate function for better maintainability.

+const isRichText = (col: ColumnType) => 
+  col.uidt === UITypes.LongText && parseProp(col?.meta)?.richMode
+
+const isAIPrompt = (col: ColumnType) =>
+  col.uidt === UITypes.LongText && parseProp(col?.meta)?.[LongTextAiMetaProp]
+
 const columnTypeName = computed(() => {
-  if (column.value.uidt === UITypes.LongText) {
-    if (parseProp(column.value?.meta)?.richMode) {
-      return UITypesName.RichText
-    }
-
-    if (parseProp(column.value?.meta)?.[LongTextAiMetaProp]) {
-      return UITypesName.AIPrompt
-    }
+  if (isRichText(column.value)) {
+    return UITypesName.RichText
+  }
+  if (isAIPrompt(column.value)) {
+    return UITypesName.AIPrompt
   }
 
   return column.value.uidt ? UITypesName[column.value.uidt] : ''
 })
packages/nc-gui/composables/useNocoAi.ts (1)

20-21: Consider documenting the reason for using Partial type

The change from IntegrationType[] to Partial<IntegrationType>[] makes the type more flexible, but it might be worth documenting why partial integrations are acceptable to maintain clarity for future developers.

packages/nocodb-sdk/src/lib/UITypes.ts (1)

191-197: Consider adding JSDoc documentation

The isAIPromptCol function would benefit from JSDoc documentation explaining:

  • Purpose of the function
  • Expected shape of the meta property
  • Return value meaning
+/**
+ * Checks if a column is configured as an AI prompt
+ * @param col - Column configuration object
+ * @returns true if the column is a LongText with AI metadata
+ */
 export function isAIPromptCol(
   col: ColumnReqType | ColumnType
 ) {
packages/nc-gui/components/smartsheet/grid/GroupByTable.vue (1)

Line range hint 299-321: Consider adding error boundaries around the Suspense component.

While the implementation of lazy-loaded forms with Suspense is good, consider adding error boundaries to gracefully handle loading failures.

+ <ErrorBoundary>
    <Suspense>
      <LazySmartsheetExpandedForm
        v-if="expandedFormRow && expandedFormDlg"
        v-model="expandedFormDlg"
        :load-row="!isPublic"
        :row="expandedFormRow"
        :state="expandedFormRowState"
        :meta="meta"
        :view="view"
        @update:model-value="addRowExpandOnClose(expandedFormRow)"
      />
    </Suspense>
+ </ErrorBoundary>
packages/nc-gui/utils/columnUtils.ts (1)

269-315: Consider refactoring isColumnInvalid for better maintainability.

The function has grown complex with multiple nested conditions. Consider breaking it down into smaller, focused functions.

+ const isButtonInvalid = (colOptions: ButtonType, aiIntegrations: Partial<IntegrationType>[], isReadOnly: boolean) => {
+   if (colOptions.type === ButtonActionsType.Webhook) {
+     return { isInvalid: !colOptions.fk_webhook_id, tooltip: 'msg.invalidColumnConfiguration' }
+   }
+   if (colOptions.type === ButtonActionsType.Url) {
+     return { isInvalid: !!colOptions.error, tooltip: 'msg.invalidColumnConfiguration' }
+   }
+   if (colOptions.type === ButtonActionsType.Ai) {
+     return {
+       isInvalid: !colOptions.fk_integration_id || 
+         (isReadOnly ? false : !!colOptions.fk_integration_id && 
+           !ncIsArrayIncludes(aiIntegrations, colOptions.fk_integration_id, 'id')),
+       tooltip: 'title.aiIntegrationMissing'
+     }
+   }
+   return { isInvalid: false, tooltip: 'msg.invalidColumnConfiguration' }
+ }

+ const isLongTextInvalid = (col: ColumnType, aiIntegrations: Partial<IntegrationType>[], isReadOnly: boolean) => {
+   if (!parseProp(col.meta)[LongTextAiMetaProp]) {
+     return { isInvalid: false, tooltip: 'msg.invalidColumnConfiguration' }
+   }
+   const colOptions = col.colOptions as ButtonType
+   return {
+     isInvalid: !colOptions.fk_integration_id || 
+       (isReadOnly ? false : !!colOptions.fk_integration_id && 
+         !ncIsArrayIncludes(aiIntegrations, colOptions.fk_integration_id, 'id')),
+     tooltip: 'title.aiIntegrationMissing'
+   }
+ }

const isColumnInvalid = (
  col: ColumnType,
  aiIntegrations: Partial<IntegrationType>[] = [],
  isReadOnly: boolean = false,
): { isInvalid: boolean; tooltip: string } => {
  switch (col.uidt) {
    case UITypes.Formula:
      return { 
        isInvalid: !!(col.colOptions as FormulaType).error,
        tooltip: 'msg.invalidColumnConfiguration'
      }
    case UITypes.Button:
      return isButtonInvalid(col.colOptions as ButtonType, aiIntegrations, isReadOnly)
    case UITypes.LongText:
      return isLongTextInvalid(col, aiIntegrations, isReadOnly)
    default:
      return { isInvalid: false, tooltip: 'msg.invalidColumnConfiguration' }
  }
}
packages/nc-gui/components/smartsheet/PlainCell.vue (1)

207-211: Consider enhancing type safety in getTextAreaValue.

While the AI prompt handling is well-implemented, consider adding type guards for better type safety.

const getTextAreaValue = (modelValue: string | null, col: ColumnType) => {
  const isRichMode = parseProp(col.meta).richMode
  if (isRichMode) {
    return modelValue?.replace(/[*_~\[\]]|<\/?[^>]+(>|$)/g, '') || ''
  }

  if (isAIPromptCol(col)) {
-   return (modelValue as AIRecordType)?.value || ''
+   const aiRecord = modelValue as AIRecordType
+   return typeof aiRecord?.value === 'string' ? aiRecord.value : ''
  }

  return modelValue || ''
}
packages/nc-gui/components/smartsheet/Cell.vue (1)

150-176: Consider optimizing the cell type determination logic.

The computed property provides a clear and maintainable way to determine cell types. However, it could be optimized to avoid multiple function calls for type checking.

Consider refactoring to use a map or switch statement for better performance:

-const cellType = computed(() => {
-  if (isAI(column.value)) return 'ai'
-  if (isTextArea(column.value)) return 'textarea'
-  // ... more conditions
-  return 'text'
-})
+const cellType = computed(() => {
+  const typeCheckers = {
+    ai: isAI,
+    textarea: isTextArea,
+    geoData: isGeoData,
+    checkbox: (col) => isBoolean(col, abstractType.value),
+    // ... more mappings
+  }
+  
+  for (const [type, checker] of Object.entries(typeCheckers)) {
+    if (checker(column.value)) return type
+  }
+  
+  return 'text'
+})
packages/nc-gui/components/smartsheet/toolbar/ViewActionMenu.vue (1)

155-158: Consider making the delay duration configurable.

The implementation improves user feedback, but the 5-second delay is hardcoded.

Consider extracting the delay duration to a constant or prop:

+const COPY_FEEDBACK_DURATION = 5000
+
 const  () => {
   await copy(view.value!.id!)
   isViewIdCopied.value = true
 
-  await ncDelay(5000)
+  await ncDelay(COPY_FEEDBACK_DURATION)
 
   isViewIdCopied.value = false
 }
packages/nc-gui/composables/useColumnCreateStore.ts (1)

113-116: Consider adding error handling for AI prompt validation.

While the implementation is correct, consider adding error handling to gracefully handle cases where formState.value might be undefined or when isAIPromptCol throws an error.

 if (isAIPromptCol(formState.value)) {
   return true
 }
+try {
+  if (formState.value && isAIPromptCol(formState.value)) {
+    return true
+  }
+} catch (e) {
+  console.error('Error validating AI prompt column:', e)
+}
packages/nc-gui/helpers/parsers/parserHelpers.ts (2)

481-484: Add type safety for ButtonActionsType comparison.

Consider using type guards to ensure type safety when checking button action types.

-if (formState?.type === ButtonActionsType.Ai) {
+if (formState?.type && formState.type === ButtonActionsType.Ai) {
   defaultColumnName = UITypesName.AIButton
 }

486-490: Consider extracting AI-related logic to a separate function.

The AI-specific naming logic could be extracted to improve code organization and reusability.

+const getAIColumnName = (formState: Record<string, any>, defaultName: string) => {
+  if (formState?.meta?.[LongTextAiMetaProp] === true) {
+    return UITypesName.AIPrompt
+  }
+  return defaultName
+}

 case UITypes.LongText: {
-  if (formState?.meta?.[LongTextAiMetaProp] === true) {
-    defaultColumnName = UITypesName.AIPrompt
-  }
+  defaultColumnName = getAIColumnName(formState, defaultColumnName)
   break
 }
packages/nc-gui/components/smartsheet/expanded-form/index.vue (1)

330-333: LGTM! Consider using a constant for the delay duration.

The implementation of a delay mechanism for user feedback is good. However, the magic number 5000 could be extracted into a named constant for better maintainability.

+ const COPY_FEEDBACK_DELAY_MS = 5000;
+
  async copyRecordUrl() {
    await copy(
      encodeURI(
        `${dashboardUrl?.value}#/${route.params.typeOrId}/${route.params.baseId}/${meta.value?.id}${
          props.view ? `/${props.view.title}` : ''
        }?rowId=${primaryKey.value}`,
      ),
    )

    isRecordLinkCopied.value = true

-   await ncDelay(5000)
+   await ncDelay(COPY_FEEDBACK_DELAY_MS)

    isRecordLinkCopied.value = false
  }
packages/nocodb/src/modules/jobs/jobs/export-import/import.service.ts (2)

Line range hint 1244-1280: Consider adding logging for workspace validation failures

While the workspace validation logic is correct, adding logging when workspace IDs don't match would help track potential security-related events.

 if (base.fk_workspace_id !== colOptions.fk_workspace_id) {
+  this.logger.warn(`Button column workspace mismatch - resetting integration. Base workspace: ${base.fk_workspace_id}, Column workspace: ${colOptions.fk_workspace_id}`);
   colOptions.fk_workspace_id = null;
   colOptions.fk_integration_id = null;
   colOptions.model = null;
 }

Line range hint 1281-1299: Refactor duplicated workspace validation logic

The workspace validation logic is duplicated between button and AI prompt columns. Consider extracting this into a shared utility function.

+private validateWorkspaceAccess(base: Base, colOptions: any) {
+  if (base.fk_workspace_id !== colOptions.fk_workspace_id) {
+    this.logger.warn(`Column workspace mismatch - resetting integration. Base workspace: ${base.fk_workspace_id}, Column workspace: ${colOptions.fk_workspace_id}`);
+    colOptions.fk_workspace_id = null;
+    colOptions.fk_integration_id = null;
+    colOptions.model = null;
+  }
+}

 // In button column handling
-if (base.fk_workspace_id !== colOptions.fk_workspace_id) {
-  colOptions.fk_workspace_id = null;
-  colOptions.fk_integration_id = null;
-  colOptions.model = null;
-}
+this.validateWorkspaceAccess(base, colOptions);

 // In AI prompt column handling
-if (base.fk_workspace_id !== colOptions.fk_workspace_id) {
-  colOptions.fk_workspace_id = null;
-  colOptions.fk_integration_id = null;
-  colOptions.model = null;
-}
+this.validateWorkspaceAccess(base, colOptions);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 36d6403 and 58a8a11.

📒 Files selected for processing (72)
  • packages/nc-gui/components/ai/PromptWithFields.vue (8 hunks)
  • packages/nc-gui/components/ai/Settings.vue (9 hunks)
  • packages/nc-gui/components/cell/AI.vue (8 hunks)
  • packages/nc-gui/components/cell/TextArea.vue (11 hunks)
  • packages/nc-gui/components/cell/attachment/index.vue (1 hunks)
  • packages/nc-gui/components/general/IntegrationIcon.vue (1 hunks)
  • packages/nc-gui/components/general/Loader.vue (1 hunks)
  • packages/nc-gui/components/nc/Button.vue (6 hunks)
  • packages/nc-gui/components/nc/List/RecordItem.vue (1 hunks)
  • packages/nc-gui/components/nc/Switch.vue (2 hunks)
  • packages/nc-gui/components/smartsheet/Cell.vue (3 hunks)
  • packages/nc-gui/components/smartsheet/Gallery.vue (1 hunks)
  • packages/nc-gui/components/smartsheet/Kanban.vue (1 hunks)
  • packages/nc-gui/components/smartsheet/PlainCell.vue (2 hunks)
  • packages/nc-gui/components/smartsheet/column/AiButtonOptions.vue (6 hunks)
  • packages/nc-gui/components/smartsheet/column/ButtonOptions.vue (2 hunks)
  • packages/nc-gui/components/smartsheet/column/EditOrAdd.vue (8 hunks)
  • packages/nc-gui/components/smartsheet/column/LongTextOptions.vue (2 hunks)
  • packages/nc-gui/components/smartsheet/column/UITypesOptionsWithSearch.vue (2 hunks)
  • packages/nc-gui/components/smartsheet/details/Fields.vue (1 hunks)
  • packages/nc-gui/components/smartsheet/expanded-form/index.vue (1 hunks)
  • packages/nc-gui/components/smartsheet/grid/GroupByTable.vue (1 hunks)
  • packages/nc-gui/components/smartsheet/grid/InfiniteTable.vue (4 hunks)
  • packages/nc-gui/components/smartsheet/grid/Table.vue (4 hunks)
  • packages/nc-gui/components/smartsheet/header/Cell.vue (1 hunks)
  • packages/nc-gui/components/smartsheet/header/CellIcon.ts (1 hunks)
  • packages/nc-gui/components/smartsheet/header/Menu.vue (4 hunks)
  • packages/nc-gui/components/smartsheet/header/VirtualCell.vue (1 hunks)
  • packages/nc-gui/components/smartsheet/toolbar/ViewActionMenu.vue (1 hunks)
  • packages/nc-gui/components/virtual-cell/Button.vue (1 hunks)
  • packages/nc-gui/components/virtual-cell/HasMany.vue (1 hunks)
  • packages/nc-gui/components/virtual-cell/ManyToMany.vue (1 hunks)
  • packages/nc-gui/components/virtual-cell/components/ListItem.vue (1 hunks)
  • packages/nc-gui/components/workspace/integrations/ConnectionsTab.vue (0 hunks)
  • packages/nc-gui/components/workspace/integrations/IntegrationsTab.vue (2 hunks)
  • packages/nc-gui/components/workspace/integrations/forms/EditOrAddCommon.vue (1 hunks)
  • packages/nc-gui/components/workspace/integrations/forms/EditOrAddDatabase.vue (2 hunks)
  • packages/nc-gui/components/workspace/project/AiCreateProject.vue (2 hunks)
  • packages/nc-gui/composables/useColumnCreateStore.ts (2 hunks)
  • packages/nc-gui/composables/useData.ts (2 hunks)
  • packages/nc-gui/composables/useInfiniteData.ts (2 hunks)
  • packages/nc-gui/composables/useIntegrationsStore.ts (8 hunks)
  • packages/nc-gui/composables/useMultiSelect/index.ts (2 hunks)
  • packages/nc-gui/composables/useNocoAi.ts (3 hunks)
  • packages/nc-gui/helpers/parsers/parserHelpers.ts (2 hunks)
  • packages/nc-gui/helpers/tiptapExtensions/mention/FieldList.vue (3 hunks)
  • packages/nc-gui/nuxt.config.ts (3 hunks)
  • packages/nc-gui/utils/cell.ts (1 hunks)
  • packages/nc-gui/utils/columnUtils.ts (4 hunks)
  • packages/nc-gui/utils/commonUtils.ts (1 hunks)
  • packages/nocodb-sdk/src/lib/Api.ts (0 hunks)
  • packages/nocodb-sdk/src/lib/UITypes.ts (3 hunks)
  • packages/nocodb-sdk/src/lib/globals.ts (1 hunks)
  • packages/nocodb-sdk/src/lib/helperFunctions.ts (1 hunks)
  • packages/nocodb-sdk/src/lib/index.ts (1 hunks)
  • packages/nocodb/src/db/BaseModelSqlv2.ts (8 hunks)
  • packages/nocodb/src/db/conditionV2.ts (2 hunks)
  • packages/nocodb/src/db/formulav2/formulaQueryBuilderv2.ts (2 hunks)
  • packages/nocodb/src/db/sortV2.ts (2 hunks)
  • packages/nocodb/src/meta/migrations/XcMigrationSourcev2.ts (3 hunks)
  • packages/nocodb/src/meta/migrations/v2/nc_069_ai_prompt.ts (1 hunks)
  • packages/nocodb/src/models/AIColumn.ts (1 hunks)
  • packages/nocodb/src/models/Column.ts (9 hunks)
  • packages/nocodb/src/models/Integration.ts (3 hunks)
  • packages/nocodb/src/models/LongTextColumn.ts (1 hunks)
  • packages/nocodb/src/models/index.ts (1 hunks)
  • packages/nocodb/src/modules/jobs/jobs/export-import/duplicate.processor.ts (2 hunks)
  • packages/nocodb/src/modules/jobs/jobs/export-import/export.service.ts (4 hunks)
  • packages/nocodb/src/modules/jobs/jobs/export-import/import.service.ts (5 hunks)
  • packages/nocodb/src/services/columns.service.ts (4 hunks)
  • packages/nocodb/src/utils/dataConversion.ts (1 hunks)
  • packages/nocodb/src/utils/globals.ts (2 hunks)
💤 Files with no reviewable changes (2)
  • packages/nc-gui/components/workspace/integrations/ConnectionsTab.vue
  • packages/nocodb-sdk/src/lib/Api.ts
🧰 Additional context used
📓 Learnings (1)
packages/nc-gui/components/smartsheet/grid/GroupByTable.vue (1)
Learnt from: DarkPhoenix2704
PR: nocodb/nocodb#8781
File: packages/nc-gui/components/smartsheet/grid/GroupBy.vue:225-232
Timestamp: 2024-11-12T03:23:04.401Z
Learning: DarkPhoenix2704 prefers to keep code implementations that prioritize readability, even if an alternative might be more concise.
🪛 Biome (1.9.4)
packages/nocodb/src/models/AIColumn.ts

[error] 26-26: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 40-40: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

packages/nocodb/src/models/LongTextColumn.ts

[error] 61-61: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 85-85: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

packages/nc-gui/composables/useIntegrationsStore.ts

[error] 296-296: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

packages/nocodb/src/models/Column.ts

[error] 921-921: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (79)
packages/nc-gui/components/nc/Switch.vue (1)

45-47: LGTM! Visual feedback enhancement for disabled state.

The addition of opacity-60 class provides better visual indication of the disabled state, improving user experience.

Also applies to: 72-74

packages/nc-gui/components/general/Loader.vue (2)

4-7: LGTM! Well-structured type definitions.

The new GeneralLoaderProps interface provides clear and explicit type definitions for the component props. The union type for size effectively captures all valid options.


9-9: LGTM! Props implementation is type-safe.

The defineProps usage with the new interface ensures type safety at compile time.

packages/nc-gui/components/nc/Button.vue (4)

23-23: LGTM! Well-typed prop definition.

The loaderSize prop is properly typed using the imported GeneralLoaderProps interface.


37-37: LGTM! Sensible default value.

The default value of 'medium' maintains backward compatibility and aligns with the button's default size.


53-53: LGTM! Proper prop destructuring.

The loaderSize is correctly added to the destructured props using toRefs.


118-118: LGTM! Consistent loader implementation.

The loaderSize prop is consistently applied to both loader instances, ensuring uniform behavior.

Also applies to: 137-137

packages/nocodb/src/modules/jobs/jobs/export-import/duplicate.processor.ts (1)

4-9: LGTM: Import statement is properly organized

The new import isAIPromptCol is correctly grouped with related imports from 'nocodb-sdk'.

packages/nc-gui/components/general/IntegrationIcon.vue (1)

5-5: LGTM! Verify existing usage.

The change to make the size prop optional with a default value of 'sm' is a good improvement for component flexibility. The type safety is maintained with proper TypeScript types.

Let's verify the existing usage to ensure 'sm' is an appropriate default:

✅ Verification successful

Making size prop optional is safe

Based on the codebase analysis, the change is safe as all existing usages of GeneralIntegrationIcon are focused on the type prop, and none explicitly set the size prop. Making it optional with a default of 'sm' won't affect current implementations across:

  • Connection tabs and forms
  • Data source creation and editing
  • AI settings
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for all usages of IntegrationIcon to verify the impact
rg -l "IntegrationIcon" --type vue | xargs rg -A 2 -B 2 "<IntegrationIcon"

Length of output: 102


Script:

#!/bin/bash
# Search for all usages of IntegrationIcon without file type restriction
rg -l "IntegrationIcon" | xargs rg -A 2 -B 2 "<IntegrationIcon"

Length of output: 63


Script:

#!/bin/bash
# First, let's find all files containing IntegrationIcon
rg -l "IntegrationIcon"

# Then, let's look for any imports or references to IntegrationIcon
rg "IntegrationIcon" -C 3

Length of output: 6996

packages/nc-gui/components/virtual-cell/Button.vue (1)

213-213: LGTM! Verify UI consistency across components.

The border radius change from rounded-lg to rounded-md looks good. This appears to be part of UI standardization.

Let's verify the border radius consistency across other button components:

✅ Verification successful

Border radius change is part of UI standardization

The change from rounded-lg to rounded-md in Button.vue appears to be part of a larger UI standardization effort. The codebase shows:

  • Most interactive elements like buttons, inputs, and menus are using rounded-md
  • rounded-lg is primarily used for larger containers, cards and modal dialogs
  • The change aligns with the design system's usage of medium radius for interactive elements
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any inconsistent border radius classes in button components
# Look for rounded-lg that might need to be updated to rounded-md

# Search for rounded-lg in Vue files
echo "Checking for rounded-lg in Vue components:"
rg "rounded-lg" --type vue

# Search for rounded-md in Vue files to verify the standard
echo "\nVerifying rounded-md usage in Vue components:"
rg "rounded-md" --type vue

Length of output: 309


Script:

#!/bin/bash
# Search for rounded-lg in all files (not just .vue)
echo "Checking for rounded-lg:"
rg "rounded-lg" 

# Search for rounded-md in all files
echo -e "\nVerifying rounded-md usage:"
rg "rounded-md"

Length of output: 66242


Script:

#!/bin/bash
# Search for rounded-md in all files, excluding minified files
echo "Checking for rounded-md usage:"
rg "rounded-md" --type-not css --type-not min

Length of output: 144


Script:

#!/bin/bash
# Search for rounded-md in all files, excluding node_modules and dist directories
echo "Checking for rounded-md usage:"
rg "rounded-md" -g '!node_modules' -g '!dist' -g '!*.min.*'

echo -e "\nChecking for rounded-lg usage:"
rg "rounded-lg" -g '!node_modules' -g '!dist' -g '!*.min.*'

Length of output: 66149

packages/nc-gui/nuxt.config.ts (3)

242-242: Verify Monaco editor language support integration

The addition of Monaco editor's JavaScript language support suggests new code editing features. Ensure this is properly integrated with the existing Monaco editor setup.

✅ Verification successful

Let me gather more information about the Monaco editor setup to verify its integration.


Based on the search results, I can now generate the final response as we have sufficient evidence about the Monaco editor integration.

Monaco editor JavaScript language support is properly integrated

The JavaScript language support is correctly added in the build configuration and the Monaco editor is well integrated across the application with:

  • Proper worker setup in plugins/monaco.ts
  • Custom editor component in components/monaco/Editor.vue
  • Formula language support in components/monaco/formula.ts
  • Consistent styling and configuration across components
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for Monaco editor configuration and usage
rg -g '!node_modules' -g '*.{vue,ts,js}' -A 5 'monaco-editor.*javascript'

Length of output: 460


Script:

#!/bin/bash
# Search for Monaco editor configuration and imports
rg -g '!node_modules' -g '*.{vue,ts,js}' -B 5 -A 5 'monaco-editor'

# Search for files that might contain Monaco editor initialization
fd -e vue -e ts -e js -X rg -l "monaco"

Length of output: 7541


258-258: Verify barcode reader implementation

The addition of vue-barcode-reader suggests new barcode scanning functionality. This should be properly integrated with error handling and fallback mechanisms.

✅ Verification successful

Let me check the implementation details of the barcode reader to verify proper error handling and fallback mechanisms.


Barcode reader implementation is properly integrated with error handling

The implementation includes comprehensive error handling and fallback mechanisms:

  • Error handling for scanner initialization with loading states
  • Validation for column selection and scanned values
  • User feedback through message system for various scenarios:
    • No rows found for scanned code
    • Multiple rows found for same code
    • Invalid column selections
  • Proper cleanup and state management
  • Type-safe value transformations based on field types
  • Graceful error recovery with console logging
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for barcode reader implementation
rg -g '!node_modules' -g '*.{vue,ts,js}' -A 5 'vue-barcode-reader'

Length of output: 1480


Script:

#!/bin/bash
# Check QrScannerButton implementation for error handling
cat packages/nc-gui/components/smartsheet/toolbar/QrScannerButton.vue

# Check form implementation for error handling
cat "packages/nc-gui/pages/index/[typeOrId]/form/[viewId]/index/index.vue"

Length of output: 18703


229-230: Verify cross-origin worker implementation

The addition of crossoriginworker suggests implementation of cross-origin web workers. This requires careful consideration of security implications.

packages/nc-gui/components/virtual-cell/components/ListItem.vue (1)

162-162: Verify the icon component migration.

The change from MaximizeIcon to GeneralIcon with 'maximize' icon looks good, but let's ensure consistency across the codebase.

Let's verify the icon usage pattern across the codebase:

✅ Verification successful

Icon migration is consistent with codebase patterns

The change from MaximizeIcon to GeneralIcon with 'maximize' icon is consistent with the codebase patterns. The search results show:

  1. The maximize icon is properly registered in iconUtils.ts and available through the icon system
  2. Other components are already using GeneralIcon with 'maximize' icon in similar expand/maximize scenarios:
    • smartsheet/grid/GroupBy.vue
    • smartsheet/calendar/DateTimeSpanningContainer.vue

The styling (w-4 h-4 scale-125) is also consistent with other icon usage in the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistent usage of maximize icon across components
# Expected: All maximize icons should use GeneralIcon component

# Check for any remaining MaximizeIcon imports
rg "MaximizeIcon"

# Check for consistent usage of maximize icon with GeneralIcon
rg -A 2 "GeneralIcon.*maximize"

# Check for any other maximize icon implementations
ast-grep --pattern 'icon="maximize"'

Length of output: 65669


Script:

#!/bin/bash
# Let's check for icon usage patterns more specifically
# 1. Check for MaximizeIcon imports and usage
rg -A 2 "MaximizeIcon" --type vue

# 2. Check for GeneralIcon with maximize icon usage
rg -A 2 '<GeneralIcon.*icon="maximize"' --type vue

# 3. Check for any other maximize icon implementations
rg -A 2 'maximize' --type vue --type ts

Length of output: 210


Script:

#!/bin/bash
# Let's check for icon usage patterns without file type restrictions
# 1. Check for MaximizeIcon imports and usage
rg -A 2 "MaximizeIcon"

# 2. Check for GeneralIcon with maximize icon usage
rg -A 2 '<GeneralIcon.*icon="maximize"'

# 3. Check for any other maximize icon implementations
rg -A 2 'maximize' packages/nc-gui/

Length of output: 7363

packages/nocodb/src/models/Column.ts (1)

1961-1974: ⚠️ Potential issue

Ensure AI metadata is inserted correctly for LongText columns

When bulk inserting LongText columns, verify that AI-related metadata is correctly handled. The condition if (column.meta?.[LongTextAiMetaProp] === true) should account for cases where meta might be undefined.

Apply this diff to fix the condition:

-if (column.meta?.[LongTextAiMetaProp] === true) {
+if (column.meta && column.meta[LongTextAiMetaProp] === true) {

Likely invalid or redundant comment.

packages/nocodb/src/services/columns.service.ts (2)

71-74: New AI conversion functions imported correctly

The functions convertAIRecordTypeToValue and convertValueToAIRecordType are correctly imported from ~/utils/dataConversion.


1623-1644: Data conversion to AIRecordType is handled properly

The convertValueToAIRecordType function is called when converting a column to an AI Prompt type, ensuring data consistency.

packages/nc-gui/components/smartsheet/header/CellIcon.ts (1)

23-24: LGTM: AI column icon handling added

The addition of the AI column type check is implemented correctly and follows the existing pattern of icon mapping.

packages/nc-gui/utils/commonUtils.ts (1)

75-102: LGTM: Well-documented search utility function

The function is thoroughly documented with clear examples and edge case handling.

packages/nc-gui/components/virtual-cell/ManyToMany.vue (1)

148-149: LGTM: UI consistency improvements

The icon update and fixed dimensions improve visual consistency and prevent layout shifts.

packages/nc-gui/components/workspace/integrations/forms/EditOrAddCommon.vue (2)

2-2: LGTM: Type-only import improves build-time optimization

The change to use TypeScript's import type syntax is a good practice as it ensures these imports are removed during compilation, reducing bundle size.


Line range hint 1-24: Verify the impact of removing loadAiIntegrations

The removal of loadAiIntegrations from the onSubmit handler might affect AI integration initialization. Let's verify if this functionality is handled elsewhere.

✅ Verification successful

Based on the review of the code, I can now generate the final response:

The removal of loadAiIntegrations is safe as AI integrations are now handled through the aiIntegrations ref

The code shows that AI integrations are now managed through the aiIntegrations ref from useNocoAi() composable, and the integration loading/saving logic is properly handled in the store:

  • AI integrations are updated in the aiIntegrations ref when:
    • Creating new integrations (saveIntegration)
    • Updating existing integrations (updateIntegration)
    • Deleting integrations (deleteIntegration)
    • Setting default integrations (setDefaultIntegration)

The removal of loadAiIntegrations from the onSubmit handler is correct as this functionality is now properly encapsulated in the integration store operations.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for loadAiIntegrations usage across the codebase
rg "loadAiIntegrations" --type vue --type ts -A 5

# Search for AI integration initialization patterns
ast-grep --pattern 'async function $name($_) {
  $$$
  loadAiIntegrations
  $$$
}'

Length of output: 162


Script:

#!/bin/bash
# Search for loadAiIntegrations usage with correct file type
rg "loadAiIntegrations" -t typescript -t vue -A 5

# Search for AI integration related patterns
rg "AI|ai.*integration" -t typescript -t vue -A 5

# Look for store related to AI integrations
fd -e ts -e vue store | xargs rg "AI|ai.*integration"

Length of output: 3210


Script:

#!/bin/bash
# Try with ripgrep without file type specification
rg "loadAiIntegrations" --no-heading

# Look for AI integration loading patterns in the store
rg "load.*ai.*integration" --no-heading

# Check the specific file for any recent changes
git log -p packages/nc-gui/components/workspace/integrations/forms/EditOrAddCommon.vue

Length of output: 65615


Script:

#!/bin/bash
# Search for loadAiIntegrations in the entire repository
rg -l "loadAiIntegrations"

# Search for AI integration related code in the store
rg "useIntegrationStore" -A 5

# Look for onSubmit handler in the file
rg "onSubmit" packages/nc-gui/components/workspace/integrations/forms/EditOrAddCommon.vue

Length of output: 7215


Script:

#!/bin/bash
# Get the full content of EditOrAddCommon.vue to see the onSubmit handler
cat packages/nc-gui/components/workspace/integrations/forms/EditOrAddCommon.vue

# Look for AI integration loading in useIntegrationsStore
cat packages/nc-gui/composables/useIntegrationsStore.ts

Length of output: 20232

packages/nc-gui/components/virtual-cell/HasMany.vue (1)

149-150: UI Enhancement: Improved icon and styling

The changes enhance the UI by:

  1. Using a more semantically appropriate "maximize" icon
  2. Improving visibility with better hover states and sizing
packages/nc-gui/components/smartsheet/column/UITypesOptionsWithSearch.vue (2)

23-23: LGTM: Consistent AI feature handling

The addition of AIPrompt to the feature flag check ensures consistent handling of AI-related features. This prevents AI options from being displayed when the feature is disabled.


129-129: LGTM: Visual distinction for AI options

The styling update appropriately distinguishes AI-related options (both AIButton and AIPrompt) with a consistent purple color theme.

packages/nc-gui/components/cell/AI.vue (4)

47-47: Simplification improves code clarity

The simplified logic for isFieldAiIntegrationAvailable makes the code more maintainable.


118-120: Good consolidation of button state logic

The new isDisabledAiButton computed property effectively consolidates all conditions for button state.


164-171: Improved accessibility with focus states

The addition of proper focus states improves keyboard navigation accessibility.


16-18: Verify permissions handling in public mode

The addition of isUIAllowed and isPublic suggests this component now handles public access scenarios. Ensure that AI generation is properly restricted in public mode.

Consider implementing rate limiting for AI generation in public mode if it's intended to be available.

✅ Verification successful

Let me verify the permissions handling in public mode by checking how isPublic and isUIAllowed are used in the component.


Let me check how isDisabledAiButton is implemented to understand the permissions handling.


Let me check the implementation of isFieldAiIntegrationAvailable and how it uses these permissions.


Based on the code analysis, I can now provide a final response about the permissions handling in public mode:

AI generation is properly restricted in public mode

The AI button is correctly disabled when:

  1. No AI integration is configured (isFieldAiIntegrationAvailable checks for fk_integration_id)
  2. The view is in public mode (isPublic is true)
  3. The user doesn't have edit permissions (!isUIAllowed('dataEdit'))

The implementation is secure as it:

  • Uses proper dependency injection for permission flags
  • Applies multiple validation layers (integration availability, public mode, UI permissions)
  • Disables both the button and tooltip when required
  • Prevents AI generation through the computed isDisabledAiButton property
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for other public mode restrictions
rg -A 3 "isPublic.*AI" 

Length of output: 65561


Script:

# Check how isPublic and isUIAllowed affect AI functionality
ast-grep --pattern 'const isPublic = inject(IsPublicInj, ref(false))'
rg -A 5 'isUIAllowed.*AI|isPublic.*AI'

Length of output: 66466


Script:

# Check isDisabledAiButton implementation and related code
ast-grep --pattern 'const isDisabledAiButton = computed'
rg -A 5 'isDisabledAiButton'

Length of output: 65763


Script:

# Check isFieldAiIntegrationAvailable implementation and usage
ast-grep --pattern 'isFieldAiIntegrationAvailable'
rg -A 5 'isFieldAiIntegrationAvailable'

Length of output: 6570

packages/nc-gui/utils/cell.ts (1)

43-45: Verify AI column type detection

The implementation looks correct but needs verification across different column types.

✅ Verification successful

Based on the search results, I can now provide a final response about the AI column type detection implementation:

AI column type detection implementation is correct and consistent

The implementation correctly identifies AI columns by checking:

  1. Column has UITypes.LongText type
  2. Column has LongTextAiMetaProp metadata flag set to true

This pattern is consistently used across the codebase:

  • In GUI utils: packages/nc-gui/utils/cell.ts
  • In SDK: packages/nocodb-sdk/src/lib/UITypes.ts
  • In database layer: packages/nocodb/src/db/BaseModelSqlv2.ts
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for consistency in AI column handling
ast-grep --pattern 'column.uidt === UITypes.LongText && $_' 

Length of output: 378


Script:

#!/bin/bash
# Let's check for all usages of LongTextAiMetaProp to ensure consistent handling
rg "LongTextAiMetaProp" -A 2

# Also check for any other AI-related type checks
rg "UITypes\.LongText.*AI|AI.*UITypes\.LongText" -A 2

Length of output: 72436


Script:

#!/bin/bash
# Let's check for all imports and usages of UITypes.LongText to ensure consistent handling
rg "UITypes\.LongText" -A 2

# Also check for any AI-related column type definitions
rg "LongTextAiMetaProp" -A 2 packages/nocodb-sdk/

Length of output: 83366

packages/nocodb/src/utils/globals.ts (1)

15-15: Verify the migration from COL_AI to COL_LONG_TEXT.

The enum entries have been renamed from COL_AI to COL_LONG_TEXT. While the change makes sense for generalizing the column type, we should ensure all references are updated.

Also applies to: 148-148

✅ Verification successful

Let me gather more information about the migration script that seems relevant to this change.


Let me check one more thing to verify if there are any AIColumn model references and their relationship with LongTextColumn.


Migration from COL_AI to COL_LONG_TEXT is properly implemented

The codebase shows a well-structured inheritance relationship where AIColumn extends LongTextColumn, and the migration script (nc_069_ai_prompt.ts) properly creates the table using COL_LONG_TEXT. The change is safe because:

  • AIColumn inherits from LongTextColumn, maintaining proper type hierarchy
  • All database operations use MetaTable.COL_LONG_TEXT consistently
  • No orphaned references to COL_AI were found in the codebase
  • The migration script properly handles the table creation with all necessary fields
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining references to the old COL_AI enum
rg "COL_AI" --type ts

# Search for places where the new COL_LONG_TEXT is being used
rg "COL_LONG_TEXT" --type ts

# Look for potential migration scripts
fd -e ts -e sql migration

Length of output: 2028


Script:

#!/bin/bash
# Check the content of the migration script that creates the COL_LONG_TEXT table
cat packages/nocodb/src/meta/migrations/v2/nc_069_ai_prompt.ts

# Look for any references to AI in column-related files
rg -A 5 "AI" packages/nocodb/src/models/Column.ts

Length of output: 1818


Script:

#!/bin/bash
# Check for AIColumn model and its relationship with LongTextColumn
rg -l "AIColumn" --type ts
cat packages/nocodb/src/models/AIColumn.ts 2>/dev/null || echo "File not found"
cat packages/nocodb/src/models/LongTextColumn.ts

Length of output: 3919

packages/nocodb-sdk/src/lib/globals.ts (1)

232-233: LGTM!

The addition of LongTextAiMetaProp constant is well-placed and follows the codebase's naming conventions. This constant will help identify AI-specific properties within long text columns.

packages/nocodb/src/db/sortV2.ts (1)

1-1: LGTM!

The import of isAIPromptCol is correctly placed and properly destructured alongside UITypes.

packages/nc-gui/components/ai/PromptWithFields.vue (3)

19-19: LGTM: New readOnly prop implementation

The readOnly prop is properly implemented with a default value and correctly typed.

Also applies to: 31-31


161-178: Verify tooltip cleanup

The tooltip implementation looks good, but let's ensure proper cleanup of tooltip instances.

✅ Verification successful

Tooltip cleanup is properly implemented

The code already has proper cleanup handling for tooltips:

  • Tooltips are stored in tooltipInstances array
  • Each instance is destroyed and array is cleared via tooltipInstances.forEach((instance) => instance?.destroy()) and tooltipInstances.length = 0
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for any other tooltip implementations that might conflict
rg -A 2 "tippy\\(" --type vue

Length of output: 58


Script:

#!/bin/bash
# Search for tooltip implementations with ripgrep, including all file types
rg -A 2 "tippy\\("

# Also search for tooltip cleanup patterns
rg -A 2 "tooltipInstances"

Length of output: 1700


235-237: Consider performance impact of margin-right

Adding margin-right to all paragraphs might affect layout performance in large documents.

✅ Verification successful

Margin-right usage is appropriate and does not impact performance

The margin-right (mr-3) is applied only to direct paragraph children within the ProseMirror editor component, which is a contained and limited scope. This styling:

  1. Is part of a scoped component style
  2. Uses Tailwind's utility class which is optimized
  3. Only affects paragraph elements within the editor, not the entire document
  4. Is necessary for proper text spacing and readability in the rich text editor
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for similar margin implementations
rg "mr-\\d+" --type vue

Length of output: 52


Script:

#!/bin/bash
# Check for similar margin implementations using ripgrep without file type restriction
rg "mr-\d+"

Length of output: 65550


Script:

#!/bin/bash
# Search for CSS files and Vue files to analyze margin usage
rg -t css -t vue "mr-\d+" --no-filename

Length of output: 69


Script:

#!/bin/bash
# Search for margin-right usage in all files
rg "mr-\d+|margin-right" --type-add 'vue:*.vue' -t vue -t css

Length of output: 65600


Script:

#!/bin/bash
# Look for the file and its context to understand the styling approach
fd "PromptWithFields.vue" --type f --exec head -n 300 {}

Length of output: 7346

packages/nc-gui/components/ai/Settings.vue (2)

10-10: LGTM: New isEditColumn prop

The isEditColumn prop is properly implemented with correct typing and default value.

Also applies to: 14-14


215-221: LGTM: Scoped styles for select component

The scoped styles properly handle the select component's border radius.

packages/nc-gui/composables/useNocoAi.ts (2)

22-23: LGTM: Simplified integration availability check

Converting aiIntegrationAvailable to a computed property that checks array length is a clean improvement over the previous implementation.


24-28: Verify error handling for undefined integrationId

The isAiIntegrationAvailableInList method should handle the case when integrationId is undefined.

✅ Verification successful

The current implementation correctly handles undefined integrationId

Looking at the implementation of ncIsArrayIncludes, it already handles the undefined case properly:

  1. The function has a default empty array parameter: array: T[] = []
  2. When integrationId is undefined, it will be passed as the value parameter and compared correctly
  3. The function first checks if the array is valid with if (!ncIsArray(array) || !array.length) return false
  4. The implementation properly handles both object and primitive comparisons
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for calls to isAiIntegrationAvailableInList to verify how undefined is handled
rg "isAiIntegrationAvailableInList\(" -A 2

Length of output: 44


Script:

#!/bin/bash
# Search for the implementation and usage of ncIsArrayIncludes to understand how it handles undefined values
ast-grep --pattern 'function ncIsArrayIncludes'

# Also search for any direct usage of the function
rg "ncIsArrayIncludes\(" -A 2

# Let's also check where this function is imported from
rg "import.*ncIsArrayIncludes"

Length of output: 3619


Script:

#!/bin/bash
# Let's check the implementation of ncIsArrayIncludes in the utils/is.ts file
cat packages/nc-gui/utils/is.ts

Length of output: 5280

packages/nocodb-sdk/src/lib/UITypes.ts (1)

3-4: LGTM: Clean import organization

The imports are well-organized and clearly related to the new AI functionality.

packages/nc-gui/components/nc/List/RecordItem.vue (1)

145-145: LGTM: Improved reactivity with direct ref usage

Using currentRow directly instead of a destructured value improves Vue's reactivity tracking.

packages/nc-gui/components/smartsheet/grid/GroupByTable.vue (1)

Line range hint 279-297: LGTM! Well-structured Table component implementation.

The Table component is well-implemented with comprehensive data management, proper v-model binding, and appropriate event handlers for all CRUD operations.

packages/nc-gui/utils/columnUtils.ts (2)

15-17: LGTM! Well-defined constants.

Constants are clearly named and properly exported.


27-32: LGTM! Consistent UI type definition.

The AIPrompt type is well-configured and follows the existing pattern.

packages/nc-gui/components/smartsheet/PlainCell.vue (1)

3-3: LGTM! Well-organized imports.

The imports are properly organized and include necessary types.

Also applies to: 10-10

packages/nocodb/src/meta/migrations/XcMigrationSourcev2.ts (1)

58-58: LGTM: Migration registration follows the established pattern.

The new AI prompt migration is properly integrated into the migration system.

Also applies to: 125-125, 249-250

packages/nc-gui/components/cell/attachment/index.vue (1)

427-427: Verify icon consistency across the codebase.

The icon has been changed from expand to maximize. Let's ensure this change is consistent with other similar UI elements.

✅ Verification successful

Based on the search results, I can now generate the final response:

Icon change appears to be consistent with codebase usage

The change from iconMap.expand to iconMap.maximize is consistent as:

  1. No instances of iconMap.expand were found in the codebase
  2. The iconMap.maximize is used consistently across several components for similar maximize/expand functionality:
  • packages/nc-gui/components/smartsheet/Kanban.vue
  • packages/nc-gui/components/smartsheet/grid/InfiniteTable.vue
  • packages/nc-gui/components/smartsheet/grid/Table.vue
  • packages/nc-gui/components/smartsheet/Gallery.vue
  • packages/nc-gui/components/cell/TextArea.vue
  • packages/nc-gui/components/cell/attachment/index.vue
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining usage of expand icon and verify maximize icon usage
# Test: Search for both old and new icon usage
rg "iconMap\.expand" --type vue
rg "iconMap\.maximize" --type vue

Length of output: 125


Script:

#!/bin/bash
# Search for both old and new icon usage without file type restriction
rg "iconMap\.expand"
rg "iconMap\.maximize"

# Also search for icon imports or definitions
rg -B 2 -A 2 "iconMap\s*=\s*"

Length of output: 1630


Script:

#!/bin/bash
# Let's check the icon definitions in the iconUtils file
cat packages/nc-gui/utils/iconUtils.ts

Length of output: 65577

packages/nocodb/src/models/Integration.ts (1)

454-456: LGTM: Added null check for config.models array

Good defensive programming practice to prevent potential runtime errors.

packages/nc-gui/components/workspace/integrations/IntegrationsTab.vue (1)

42-42: LGTM: Added dynamic integrations loading

Good addition to load dynamic integrations when the component is mounted.

Also applies to: 216-217

packages/nc-gui/components/smartsheet/column/ButtonOptions.vue (2)

Line range hint 174-190: LGTM: Added comprehensive validation for AI button type

Good addition of validation rules with clear error messages for AI button's required fields.


212-215: LGTM: Added consistent styling for AI buttons

Good UX consideration with appropriate theme and color choices for AI context.

packages/nc-gui/components/smartsheet/Gallery.vue (1)

376-376: LGTM: Icon update for consistency

The change from iconMap.expand to iconMap.maximize maintains visual consistency across the application.

packages/nc-gui/components/workspace/project/AiCreateProject.vue (3)

31-32: LGTM: Added event tracking dependency

The $e dependency is properly injected for event tracking.


150-164: LGTM: Enhanced prompt construction with optional fields

The prompt construction logic properly handles optional organization, industry, and audience information, concatenating them only when provided. The event emission helps with tracking AI generation usage.


Line range hint 431-434: LGTM: Added delay for better UX

The 5-second delay after copying the field ID provides better user feedback before resetting the copied state.

packages/nc-gui/components/smartsheet/header/Menu.vue (3)

48-49: LGTM: Added AI integration dependency

The aiIntegrations dependency is properly injected for AI-related validation.


52-62: LGTM: Added column validation logic

The columnInvalid computed property properly encapsulates the validation logic for columns, providing both validation state and tooltip messages.


Line range hint 451-465: LGTM: Enhanced invalid column visualization

The template properly uses the computed property to display validation state and tooltip messages for invalid columns.

packages/nc-gui/composables/useData.ts (1)

2-2: LGTM! AI prompt column handling is properly integrated.

The changes correctly integrate AI prompt column handling within the existing column type checks. The implementation follows the established patterns and is placed appropriately alongside other special column types.

Also applies to: 289-289

packages/nocodb/src/modules/jobs/jobs/export-import/export.service.ts (3)

2-8: LGTM! Import organization is clean and focused.

The imports are well-organized and properly grouped, with the new LongTextAiMetaProp import added alongside related imports.


146-160: LGTM! Proper handling of workspace-scoped entities.

The implementation correctly preserves workspace and integration IDs during export, which is essential for maintaining relationships within the same workspace. The handling of output_column_ids is also properly implemented.


628-636: LGTM! Robust error handling for LongText AI metadata serialization.

The implementation properly handles the serialization of LongText AI metadata with appropriate error handling:

  • Checks for the presence of AI metadata before processing
  • Uses try-catch for JSON stringification
  • Falls back to the original value if stringification fails
packages/nocodb/src/db/formulav2/formulaQueryBuilderv2.ts (2)

5-5: LGTM: Import added for AI metadata property

The import of LongTextAiMetaProp is correctly added to support the new AI-related functionality.


832-872: Well-structured database-specific JSON handling for AI fields

The implementation properly handles JSON extraction for AI fields across different database types:

  • PostgreSQL: Uses jsonb->>'value' with proper quote trimming
  • MySQL: Uses JSON_UNQUOTE(JSON_EXTRACT())
  • SQLite: Uses json_extract()
  • MSSQL: Uses JSON_VALUE()

The code includes proper fallback to handle non-AI fields.

packages/nc-gui/components/smartsheet/Kanban.vue (1)

1146-1146: LGTM: Icon update for better visual consistency

Changed from expand to maximize icon in the context menu to maintain consistency with other components.

packages/nc-gui/composables/useMultiSelect/index.ts (2)

6-6: LGTM: Added type support for AI records

The import of AIRecordType properly adds type safety for AI-related operations.


292-300: Enhanced clipboard handling for AI fields

The implementation correctly:

  • Checks for AI metadata property
  • Extracts the value from AI record structure
  • Maintains existing behavior for non-AI fields
packages/nocodb/src/modules/jobs/jobs/export-import/import.service.ts (1)

Line range hint 1-182: LGTM: AI prompt column filtering is properly integrated

The addition of isAIPromptCol check in the column filtering logic is clean and consistent with how other special column types are handled.

packages/nocodb-sdk/src/lib/index.ts (1)

15-15: LGTM: Export addition for AI prompt column detection

The addition of isAIPromptCol export is well-placed and aligns with the AI functionality enhancements. This export is appropriately utilized across various components for AI prompt column detection.

packages/nocodb/src/models/index.ts (1)

51-52: LGTM: New column type exports for AI functionality

The addition of LongTextColumn and AIColumn exports properly extends the model's capabilities to handle AI-related features. These exports are well-structured and align with the existing column type pattern.

packages/nc-gui/composables/useInfiniteData.ts (2)

2-2: LGTM: Import addition for AI prompt detection

The isAIPromptCol import is properly added alongside related UITypes imports.


Line range hint 919-923: LGTM: AI prompt column handling in row updates

The addition of isAIPromptCol(col) check ensures that AI prompt columns are properly updated when row properties change, consistent with the handling of other special column types.

packages/nc-gui/components/smartsheet/column/AiButtonOptions.vue (4)

471-475: LGTM: Added tooltip for truncated text

The addition of NcTooltip improves user experience by showing the full text when truncated.


687-688: LGTM: Enhanced visual feedback through conditional styling

The text color changes provide clear visual feedback based on the selection state of records, output columns, and input columns.


Line range hint 698-711: LGTM: Added semantic status indicators

The conditional styling for status indicators uses semantic color classes (green for success, red for error) to provide clear visual feedback on validation states.

Also applies to: 724-729


369-371: LGTM: New edit mode prop added to AiSettings

The addition of :is-edit-column="isEdit" prop enables edit mode handling in the AiSettings component.

✅ Verification successful

LGTM: isEditColumn prop is properly integrated

The prop :is-edit-column="isEdit" is correctly implemented:

  • Defined in packages/nc-gui/components/ai/Settings.vue with proper TypeScript interface
  • Used consistently across multiple components in the codebase
  • Follows the same pattern as other components that use this prop for edit mode handling
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify the usage of isEdit prop in AiSettings component
ast-grep --pattern 'const isEdit = ref<boolean>($$$)' 

Length of output: 55


Script:

#!/bin/bash
# Search for isEdit prop definition and usage in AiSettings component
fd "AiSettings.vue" --exec rg -A 5 "isEdit" {}

# Search for isEdit prop in AiButtonOptions.vue
rg -A 5 "isEdit" "packages/nc-gui/components/smartsheet/column/AiButtonOptions.vue"

Length of output: 655


Script:

#!/bin/bash
# Let's find the AiSettings component definition to verify prop declaration
fd "AiSettings.vue" --exec cat {}

# Also search for any other usages of isEditColumn prop
rg "isEditColumn|is-edit-column" --type vue

Length of output: 109


Script:

#!/bin/bash
# Search for AiSettings component and its props
fd "AiSettings" --exec cat {}

# Search for isEditColumn or is-edit-column without file type restriction
rg "isEditColumn|is-edit-column"

Length of output: 12093

packages/nc-gui/components/workspace/integrations/forms/EditOrAddDatabase.vue (2)

661-662: LGTM: Improved import URL button consistency

The button size and styling changes improve visual consistency with other UI elements.

Also applies to: 666-666


675-681: LGTM: Added autofocus to import URL textarea

The autofocus implementation improves user experience by automatically focusing the textarea when the dialog opens.

Comment on lines +133 to +136
A3E2
if (isAiButton(column.value)) {
return UITypesName.AIButton
}

Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Missing import for isAiButton function

The isAiButton function is defined in packages/nc-gui/utils/cell.ts but is not imported in VirtualCell.vue. The function exists in the codebase but needs to be properly imported.

  • Add the following import to VirtualCell.vue:
    import { isAiButton } from '~/utils/cell'
🔗 Analysis chain

Verify the implementation of isAiButton function

The code introduces a check for AI buttons, but the isAiButton function is not imported or defined in the visible code. This could lead to runtime errors.

Let's verify the existence and implementation of the isAiButton function:

Additionally, ensure that UITypesName.AIButton is properly defined:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for isAiButton function definition and its imports
# Expected: Find the function definition and any imports

# Search for function definition
echo "Searching for isAiButton function definition..."
rg "function isAiButton|const isAiButton|export const isAiButton" -A 5

# Search for imports
echo "Searching for isAiButton imports..."
rg "import.*isAiButton" -A 1

Length of output: 2007


Script:

#!/bin/bash
# Description: Search for AIButton type definition
# Expected: Find the type definition in UITypes/UITypesName

echo "Searching for AIButton type definition..."
rg "AIButton.*=|enum.*AIButton|type.*AIButton" -A 2

Length of output: 1505


Script:

#!/bin/bash
# Let's verify the import of isAiButton in VirtualCell.vue
echo "Searching for imports in VirtualCell.vue..."
rg "import.*cell" packages/nc-gui/components/smartsheet/header/VirtualCell.vue -A 2

# Let's also verify UITypesName import and usage
echo "Searching for UITypesName imports..."
rg "import.*UITypesName" packages/nc-gui/components/smartsheet/header/VirtualCell.vue -A 2

# Let's check the full content of VirtualCell.vue to understand the context
echo "Checking VirtualCell.vue content..."
cat packages/nc-gui/components/smartsheet/header/VirtualCell.vue

Length of output: 10749

Comment on lines +135 to +149
await sqlClient.raw(
`UPDATE ??
SET ?? = JSON_QUERY('{"value":' + ?? + ',"lastModifiedBy":' + ? + ',"lastModifiedTime":' + ? + ',"isStale":' + ? + '}')
WHERE ?? is not null;`,
[
baseModel.getTnPath(table.table_name),
column.column_name,
column.column_name,
commonRecord.lastModifiedBy.toString(),
commonRecord.lastModifiedTime.toString(),
commonRecord.isStale,
column.column_name,
],
);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Address potential SQL injection risk due to string concatenation in MSSQL query

In the MSSQL block of the convertValueToAIRecordType function, the SQL query constructs a JSON string by concatenating parameters directly into the string. This practice can lead to SQL injection vulnerabilities if the parameters are not properly sanitized.

Modify the query to use parameter binding instead of string concatenation. Here's how you can adjust the MSSQL query:

 await sqlClient.raw(
   `UPDATE ??
-    SET ?? = JSON_QUERY('{"value":' + ?? + ',"lastModifiedBy":' + ? + ',"lastModifiedTime":' + ? + ',"isStale":' + ? + '}')
+    SET ?? = JSON_QUERY(?)
     WHERE ?? is not null;`,
   [
     baseModel.getTnPath(table.table_name),
     column.column_name,
-    column.column_name,
-    commonRecord.lastModifiedBy.toString(),
-    commonRecord.lastModifiedTime.toString(),
-    commonRecord.isStale,
+    JSON.stringify({
+      value: sqlClient.raw('??', [column.column_name]),
+      lastModifiedBy: commonRecord.lastModifiedBy.toString(),
+      lastModifiedTime: commonRecord.lastModifiedTime.toString(),
+      isStale: commonRecord.isStale,
+    }),
     column.column_name,
   ],
 );

This change ensures that the parameters are safely bound and reduces the risk of SQL injection.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
F438
await sqlClient.raw(
`UPDATE ??
SET ?? = JSON_QUERY('{"value":' + ?? + ',"lastModifiedBy":' + ? + ',"lastModifiedTime":' + ? + ',"isStale":' + ? + '}')
WHERE ?? is not null;`,
[
baseModel.getTnPath(table.table_name),
column.column_name,
column.column_name,
commonRecord.lastModifiedBy.toString(),
commonRecord.lastModifiedTime.toString(),
commonRecord.isStale,
column.column_name,
],
);
}
await sqlClient.raw(
`UPDATE ??
SET ?? = JSON_QUERY(?)
WHERE ?? is not null;`,
[
baseModel.getTnPath(table.table_name),
column.column_name,
JSON.stringify({
value: sqlClient.raw('??', [column.column_name]),
lastModifiedBy: commonRecord.lastModifiedBy.toString(),
lastModifiedTime: commonRecord.lastModifiedTime.toString(),
isStale: commonRecord.isStale,
}),
column.column_name,
],
);
}

Comment on lines +1027 to +1028
enabled: isAIPromptCol(field) || isAiButton(field),
disabled: !(field?.colOptions as ButtonType)?.fk_integration_id,
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Missing import statement for 'isAiButton' function

The function isAiButton is used in lines 1027 and 1051 but is not imported, which will cause a ReferenceError at runtime.

Apply this diff to add the missing import:

 import {
   type ButtonType,
   type ColumnReqType,
   type ColumnType,
   type TableType,
   UITypes,
   type ViewType,
   ViewTypes,
   isAIPromptCol,
+  isAiButton,
   isCreatedOrLastModifiedByCol,
   isCreatedOrLastModifiedTimeCol,
   isLinksOrLTAR,
   isSystemColumn,
   isVirtualCol,
 } from 'nocodb-sdk'

Also applies to: 1051-1051

Comment on lines +2249 to +2252
class="cursor-pointer flex items-center border-1 border-gray-100 active:ring rounded-md p-1 hover:(bg-white border-nc-border-gray-medium)"
>
<component
:is="iconMap.expand"
:is="iconMap.maximize"
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Undefined 'iconMap' causes ReferenceError

The variable iconMap is used in line 2252 but is not defined or imported, which will result in a ReferenceError at runtime.

To fix this issue, import and initialize iconMap in the script section.

Add the following code in your script setup:

 const { $e } = useNuxtApp()

+const { iconMap } = useNocoIcons()

 const { api } = useApi()

Ensure that useNocoIcons is imported as well:

 import { useNuxtApp } from '#imports'
+import { useNocoIcons } from 'path/to/useNocoIcons' // Adjust the import path as necessary

Committable suggestion skipped: line range outside the PR's diff.

@@ -92,19 +99,24 @@ export default {

<template>
<div
class="w-64 bg-white scroll-smooth nc-mention-list nc-scrollbar-md border-1 border-gray-200 rounded-lg max-h-64 !py-2 shadow-lg"
class="w-64 bg-white scroll-smooth nc-mention-list nc-scrollbar-thin border-1 border-gray-200 rounded-lg max-h-64 !py-2 px-2 shadow-lg"
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Consider using a lower z-index value for the mention list

Looking at the z-index values used across the codebase, most UI components use values between 1-100, with some special cases like modals using 1000+. A z-index of 10000 is unnecessarily high. Consider:

  • Using a z-index between 50-100 which should be sufficient for a dropdown/mention list
  • Following the existing pattern where similar components like dropdowns use z-10 to z-50
  • If higher values are needed, stay consistent with other overlays that use z-1000 range
🔗 Analysis chain

Review the high z-index value in tooltip

The z-index of 10000 seems unnecessarily high and might interfere with other overlay components. Consider:

  1. Using a lower z-index value
  2. Using z-index variables from your design system for consistency

Also applies to: 110-110, 114-119

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other z-index values in the codebase
rg -A 1 "z-?index|z-?[0-9]+" --type vue

Length of output: 69


Script:

#!/bin/bash
# Search for z-index values in all files (not just .vue)
rg -A 1 "z-?index|z-?[0-9]+" --type-add 'vue:*.vue'

# Also search for Tailwind z-index classes
rg -A 1 "class=.*z-\d+" --type-add 'vue:*.vue'

Length of output: 65638


Script:

#!/bin/bash
# Search for z-index CSS classes and styles in Vue files
rg -A 1 'z-\d+|z-index' --type-add 'vue:*.vue' --type vue

# Search for Tailwind z-index classes in the codebase
rg -A 1 'class=.*z-\[.*\]' --type-add 'vue:*.vue' --type vue

Length of output: 41284

Comment on lines +921 to +925
if (ai.prompt && ai.prompt.match(/{column_id}/)) {
ai.error = `Field '${col.title}' not found`;
await AIColumn.update(context, aiCol.id, ai, ncMeta);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Use optional chaining to prevent potential runtime error

In the condition if (ai.prompt && ai.prompt.match(/{column_id}/)), if ai.prompt is null or undefined, calling ai.prompt.match will result in a runtime error. Use optional chaining to safely access the match method.

Apply this diff to fix the issue:

-if (ai.prompt && ai.prompt.match(/{column_id}/)) {
+if (ai.prompt?.match(/{column_id}/)) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (ai.prompt && ai.prompt.match(/{column_id}/)) {
ai.error = `Field '${col.title}' not found`;
await AIColumn.update(context, aiCol.id, ai, ncMeta);
}
}
if (ai.prompt?.match(/{column_id}/)) {
ai.error = `Field '${col.title}' not found`;
await AIColumn.update(context, aiCol.id, ai, ncMeta);
}
}
🧰 Tools
🪛 Biome (1.9.4)

[error] 921-921: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

Comment on lines +855 to +856
enabled: isAIPromptCol(field) || isAiButton(field),
disabled: !(field?.colOptions as ButtonType)?.fk_integration_id,
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Define the isAiButton function or import it if missing

The function isAiButton(field) is used but not defined or imported in the code. This will lead to a ReferenceError at runtime. Ensure that isAiButton is properly defined or imported.

Comment on lines +1606 to +1617
if (colBody.prompt_raw) {
await table.getColumns(context);

prompt = colBody.prompt_raw.replace(/{(.*?)}/g, (match, p1) => {
const column = table.columns.find((c) => c.title === p1);

if (!column) {
NcError.badRequest(`Field '${p1}' not found`);
}

return `{${column.id}}`;
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Optimize regular expression to prevent potential performance issues

The regular expression /{(.*?)}/g used in replace could cause performance issues due to potential catastrophic backtracking. Consider refining the regex to be more specific or using a safer method to parse placeholders.

Suggest modifying the regex as follows:

-prompt = colBody.prompt_raw.replace(/{(.*?)}/g, (match, p1) => {
+prompt = colBody.prompt_raw.replace(/{([^{}]+)}/g, (match, p1) => {

This change ensures that placeholder patterns are correctly matched without leading to performance issues.

Also applies to: 2289-2300

Comment on lines +5721 to +5724
insertDatas.map(
async (d) =>
await this.prepareNocoData(d, true, cookie, null, { raw }),
),
Copy link
Contributor

Choose a reason for hiding this comment

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

< C95D input type="hidden" name="_method" value="put" autocomplete="off" />

⚠️ Potential issue

Ensure promises are properly awaited in asynchronous operations

The async function within insertDatas.map is invoked without awaiting the resulting promises. This could lead to unhandled promises and unexpected behavior during bulk insert operations. To ensure all prepareNocoData promises are resolved before proceeding, wrap the map call with await Promise.all().

Apply this diff to fix the issue:

- insertDatas.map(
+ await Promise.all(
    insertDatas.map(
      async (d) =>
        await this.prepareNocoData(d, true, cookie, null, { raw }),
    ),
+ );

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +474 to +499
// unbind all buttons and long texts associated with this integration
await ncMeta.metaUpdate(
this.fk_workspace_id ? this.fk_workspace_id : RootScopes.WORKSPACE,
RootScopes.WORKSPACE,
MetaTable.COL_BUTTON,
{
fk_integration_id: null,
model: null,
},
{
fk_integration_id: this.id,
},
);

await ncMeta.metaUpdate(
this.fk_workspace_id ? this.fk_workspace_id : RootScopes.WORKSPACE,
RootScopes.WORKSPACE,
MetaTable.COL_LONG_TEXT,
{
fk_integration_id: null,
model: null,
},
{
fk_integration_id: this.id,
},
);
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider extracting duplicated unbinding logic into a separate method

The unbinding logic for buttons and long texts is duplicated between delete and softDelete methods. Consider extracting this into a reusable method to improve maintainability.

+ private async unbindButtonsAndLongTexts(ncMeta) {
+   await ncMeta.metaUpdate(
+     this.fk_workspace_id ? this.fk_workspace_id : RootScopes.WORKSPACE,
+     RootScopes.WORKSPACE,
+     MetaTable.COL_BUTTON,
+     {
+       fk_integration_id: null,
+       model: null,
+     },
+     {
+       fk_integration_id: this.id,
+     },
+   );
+
+   await ncMeta.metaUpdate(
+     this.fk_workspace_id ? this.fk_workspace_id : RootScopes.WORKSPACE,
+     RootScopes.WORKSPACE,
+     MetaTable.COL_LONG_TEXT,
+     {
+       fk_integration_id: null,
+       model: null,
+     },
+     {
+       fk_integration_id: this.id,
+     },
+   );
+ }

  async delete(ncMeta = Noco.ncMeta) {
    const sources = await this.getSources(ncMeta, true);
    for (const source of sources) {
      await source.delete(
        {
          workspace_id: this.fk_workspace_id,
          base_id: source.base_id,
        },
        ncMeta,
      );
    }

-   await ncMeta.metaUpdate(/*...*/)
-   await ncMeta.metaUpdate(/*...*/)
+   await this.unbindButtonsAndLongTexts(ncMeta);

    return await ncMeta.metaDelete(/*...*/);
  }

  async softDelete(ncMeta = Noco.ncMeta) {
    const sources = await this.getSources(ncMeta, true);
    for (const source of sources) {
      await source.softDelete(/*...*/);
    }

-   await ncMeta.metaUpdate(/*...*/)
-   await ncMeta.metaUpdate(/*...*/)
+   await this.unbindButtonsAndLongTexts(ncMeta);

    await ncMeta.metaUpdate(/*...*/);
  }

Also applies to: 522-547

Copy link
Contributor
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 15

🧹 Outside diff range and nitpick comments (62)
packages/nc-gui/components/smartsheet/expanded-form/index.vue (1)

330-333: LGTM! Consider extracting the delay duration.

The implementation provides good user feedback by temporarily showing the copy confirmation. However, the magic number 5000 could be extracted to a named constant for better maintainability.

+const COPY_FEEDBACK_DURATION_MS = 5000;
+
 const copyRecordUrl = async () => {
   await copy(
     encodeURI(
       `${dashboardUrl?.value}#/${route.params.typeOrId}/${route.params.baseId}/${meta.value?.id}${
         props.view ? `/${props.view.title}` : ''
       }?rowId=${primaryKey.value}`,
     ),
   )
 
   isRecordLinkCopied.value = true
 
-  await ncDelay(5000)
+  await ncDelay(COPY_FEEDBACK_DURATION_MS)
 
   isRecordLinkCopied.value = false
 }
packages/nc-gui/components/general/IntegrationIcon.vue (1)

Line range hint 3-9: Consider adding JSDoc documentation for props.

To improve developer experience, consider adding JSDoc comments to document the props interface:

+ /**
+  * Props for IntegrationIcon component
+  * @prop {string} type - The type of integration icon to display
+  * @prop {('sx'|'sm'|'md'|'lg'|'xl'|'xxl')} [size='sm'] - The size of the icon
+  */
  defineProps<{
    type: string
    size?: 'sx' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl'
  }>(),
packages/nc-gui/components/smartsheet/toolbar/ViewActionMenu.vue (1)

155-158: Add error handling and extract magic number

While the copy feedback implementation is good, consider these improvements:

  1. Add error handling for the copy operation
  2. Extract the delay duration to a constant for better maintainability
+ const COPY_FEEDBACK_DURATION = 5000 // ms
+
  const  () => {
-   await copy(view.value!.id!)
-   isViewIdCopied.value = true
-   await ncDelay(5000)
-   isViewIdCopied.value = false
+   try {
+     await copy(view.value!.id!)
+     isViewIdCopied.value = true
+     await ncDelay(COPY_FEEDBACK_DURATION)
+   } catch (error) {
+     message.error(t('msg.error.copyToClipboardError'))
+   } finally {
+     isViewIdCopied.value = false
+   }
  }
packages/nc-gui/utils/commonUtils.ts (2)

75-102: Minor inconsistency in documentation example

The example on line 96 shows usage with null values, but the function's type signature doesn't include null as a possible type. Consider either:

  1. Updating the example to match the type signature, or
  2. Adding null to the type signature if it should be supported
-searchCompare([null, undefined, "test"], "TEST"); // true
+searchCompare([undefined, "test"], "TEST"); // true

103-117: Consider caching toLowerCase results for better performance

The current implementation calls toLowerCase() for each comparison. For array inputs, this means multiple conversions of the same query string. Consider caching the lowercase query:

 export const searchCompare = (source?: string | number | (string | number | undefined)[], query?: string): boolean => {
+  const normalizedQuery = (query || '').toLowerCase()
   if (ncIsArray(source)) {
     return source.some((item) => {
       return (item || '')
         .toString()
         .toLowerCase()
-        .includes((query || '').toLowerCase())
+        .includes(normalizedQuery)
     })
   }

   return (source || '')
     .toString()
     .toLowerCase()
-    .includes((query || '').toLowerCase())
+    .includes(normalizedQuery)
 }
packages/nc-gui/components/smartsheet/column/AiButtonOptions.vue (1)

687-688: Consider extracting repeated conditional logic into computed properties

The conditional class bindings contain repeated logic across multiple elements. This could be simplified for better maintainability.

Consider refactoring like this:

+ const isValid = computed(() => !!(selectedRecordPk && outputColumnIds.length && inputColumns.length))
+ const getStatusClass = computed(() => ({
+   'text-nc-border-gray-dark': !isValid.value,
+   'text-nc-content-purple-dark': isValid.value
+ }))
+ const getIndicatorClass = (condition: boolean) => ({
+   'bg-nc-bg-green-dark text-nc-content-green-dark': condition,
+   'bg-nc-bg-red-dark text-nc-content-red-dark': !condition
+ })

- :class="{
-   'text-nc-border-gray-dark': !(selectedRecordPk && outputColumnIds.length && inputColumns.length),
-   'text-nc-content-purple-dark': !!(selectedRecordPk && outputColumnIds.length && inputColumns.length),
- }"
+ :class="getStatusClass"

- :class="inputColumns.length
-   ? 'bg-nc-bg-green-dark text-nc-content-green-dark'
-   : 'bg-nc-bg-red-dark text-nc-content-red-dark'"
+ :class="getIndicatorClass(inputColumns.length > 0)"

Also applies to: 698-702, 711-715, 724-728

packages/nc-gui/components/virtual-cell/HasMany.vue (3)

Line range hint 13-17: Consider simplifying dialog state management

The current implementation uses separate boolean flags (listItemsDlg and childListDlg) along with watchers to manage dialog states. Consider these improvements:

  1. Use a single state variable with an enum/string type:
const dialogState = ref<'none' | 'list' | 'child'>('none')
  1. Replace the watchers with computed properties:
const isOpen = computed(() => dialogState.value !== 'none')

This would simplify the state management and reduce the need for multiple watchers.

Also applies to: 76-108


Line range hint 39-49: Enhance error handling in cells computed property

The current implementation might not handle all edge cases gracefully. Consider adding more robust error handling:

 const cells = computed(() =>
   localCellValue.value.reduce((acc, curr) => {
-    if (!relatedTableDisplayValueProp.value) return acc
+    if (!relatedTableDisplayValueProp.value || !curr) return acc
 
     const value = curr[relatedTableDisplayValueProp.value]
+    if (value === undefined) return acc
 
     return [...acc, { value, item: curr }]
   }, []),
 )

Line range hint 148-156: Enhance accessibility for action icons

The action icons lack proper accessibility attributes. Consider adding:

 <GeneralIcon
   icon="maximize"
   class="select-none transform text-sm nc-action-icon text-gray-500/50 hover:text-gray-500 nc-arrow-expand h-3 w-3"
+  role="button"
+  tabindex="0"
+  aria-label="Expand list"
   @click.stop="openChildList"
+  @keydown.enter="openChildList"
+  @keydown.space.prevent="openChildList"
 />
packages/nc-gui/components/smartsheet/column/ButtonOptions.vue (2)

Line range hint 174-212: LGTM! Consider extracting AI-specific validators for better maintainability.

The validation logic for AI button type is correct and comprehensive. However, the nested ternary condition could be extracted into a computed property for better readability.

Consider refactoring to:

+ const isAiButtonType = computed(() => 
+   (isEdit.value ? vModel.value.colOptions?.type : vModel.value.type) === ButtonActionsType.Ai
+ )

  const validators = {
-   ...((isEdit.value ? vModel.value.colOptions?.type : vModel.value.type) === ButtonActionsType.Ai
+   ...(isAiButtonType.value
      ? {
          output_column_ids: [
            {
              required: true,
              message: 'At least one output field is required for AI Button',
            },
          ],
          // ... rest of the AI validators
        }
      : {}),
  }

Line range hint 353-367: Consider resetting all AI-specific fields when changing button type.

When switching from AI button type to other types, only formula_raw is reset. Consider resetting all AI-specific fields to maintain data consistency.

 const handleUpdateActionType = (type: ButtonActionsType) => {
   // We are using `formula_raw` in both type url & ai, so it's imp to reset it
   if (type !== ButtonActionsType.Ai) {
     setAdditionalValidations({
       formula_raw: validators.formula_raw,
     })
+    // Reset all AI-specific fields
+    vModel.value.output_column_ids = ''
+    vModel.value.fk_integration_id = undefined
   }
   vModel.value.formula_raw = ''
 }
packages/nc-gui/composables/useNocoAi.ts (1)

24-28: Consider adding input validation for integrationId

While the implementation is good, consider adding validation for the integrationId parameter to handle edge cases like empty strings.

 const isAiIntegrationAvailableInList = (integrationId?: string) => {
   if (!aiIntegrationAvailable.value) return false
+  if (!integrationId?.trim()) return false
 
   return ncIsArrayIncludes(aiIntegrations.value, integrationId, 'id')
 }
packages/nc-gui/components/virtual-cell/Button.vue (1)

Line range hint 1-456: Consider future refactoring opportunities

While not directly related to the current changes, here are some suggestions for future improvements:

  1. Extract URL handling logic into a separate utility function
  2. Consider using a design token system for colors to reduce SCSS repetition
  3. Implement error boundaries for more robust error handling
  4. Consider breaking down the component into smaller subcomponents for better maintainability

Example of extracting URL handling:

// utils/url.ts
export function normalizeUrl(url: string): string {
  if (!url.trim()) return ''
  
  const hasProtocol = /^(https?|ftp|mailto|file):\/\//.test(url)
  const normalizedUrl = hasProtocol ? url : `https://${url.trim()}`
  
  try {
    return decodeURI(normalizedUrl) === normalizedUrl 
      ? encodeURI(normalizedUrl) 
      : normalizedUrl
  } catch {
    return encodeURI(normalizedUrl)
  }
}

Then in the component:

-    let url = `${cellValue.value?.url}`
-    url = /^(https?|ftp|mailto|file):\/\//.test(url) ? url : url.trim() ? `https://${url}` : ''
-    try {
-      url = decodeURI(url) === url ? encodeURI(url) : url
-    } catch {
-      url = encodeURI(url)
-    }
+    const url = normalizeUrl(cellValue.value?.url || '')
packages/nc-gui/components/virtual-cell/components/ListItem.vue (1)

Line range hint 158-164: Enhance accessibility attributes for interactive elements.

Consider adding ARIA attributes to improve accessibility:

 <button
   v-e="['c:row-expand:open']"
   :tabindex="-1"
   class="z-10 flex items-center justify-center nc-expand-item !group-hover:visible !invisible !h-7 !w-7 transition-all !hover:children:(w-4.5 h-4.5)"
+  :aria-expanded="false"
+  aria-label="Expand item"
   @click.stop="$emit('expand', row)"
 >
   <GeneralIcon icon="maximize" class="flex-none w-4 h-4 scale-125" />
 </button>
packages/nc-gui/utils/columnUtils.ts (2)

27-32: Add virtual: 1 to AIPrompt for consistency

In the uiTypes array, other virtual types like AIButton include the virtual property set to 1. For consistency and clarity, consider adding virtual: 1 to the AIPrompt entry.

Apply this diff to include the virtual property:

 {
   name: AIPrompt,
   icon: iconMap.cellAi,
+  virtual: 1,
   isNew: 1,
   deprecated: 0,
 },

269-315: Refactor duplicated AI integration validation logic

The logic for validating AI integration IDs in both the ButtonActionsType.Ai case and the UITypes.LongText case is duplicated. Extracting this logic into a helper function would reduce code duplication and enhance maintainability.

Here's how you might refactor the code:

  1. Create a helper function:

    function isAiIntegrationInvalid(
      colOptions: ButtonType,
      aiIntegrations: Partial<IntegrationType>[],
      isReadOnly: boolean
    ): boolean {
      return (
        !colOptions.fk_integration_id ||
        (!isReadOnly &&
          !!colOptions.fk_integration_id &&
          !ncIsArrayIncludes(aiIntegrations, colOptions.fk_integration_id, 'id'))
      );
    }
  2. Update the ButtonActionsType.Ai case:

      } else if (colOptions.type === ButtonActionsType.Ai) {
    -   result.isInvalid =
    -     !colOptions.fk_integration_id ||
    -     (isReadOnly
    -       ? false
    -       : !!colOptions.fk_integration_id && !ncIsArrayIncludes(aiIntegrations, colOptions.fk_integration_id, 'id'))
    +   result.isInvalid = isAiIntegrationInvalid(colOptions, aiIntegrations, isReadOnly);
        result.tooltip = 'title.aiIntegrationMissing';
      }
  3. Update the UITypes.LongText case:

      if (parseProp(col.meta)[LongTextAiMetaProp]) {
        const colOptions = col.colOptions as ButtonType;
    -   result.isInvalid =
    -     !colOptions.fk_integration_id ||
    -     (isReadOnly
    -       ? false
    -       : !!colOptions.fk_integration_id && !ncIsArrayIncludes(aiIntegrations, colOptions.fk_integration_id, 'id'))
    +   result.isInvalid = isAiIntegrationInvalid(colOptions, aiIntegrations, isReadOnly);
        result.tooltip = 'title.aiIntegrationMissing';
      }
packages/nc-gui/helpers/tiptapExtensions/mention/FieldList.vue (1)

Line range hint 89-94: Enhance robustness of selectItem method

Good addition of the null check, but there's room for improvement:

  1. The _e parameter is unused
  2. The id is derived directly from item.title without validation

Consider this enhanced implementation:

-  selectItem(index, _e) {
+  selectItem(index) {
     const item = this.items[index]
 
-    if (item) {
+    if (item?.title) {
       this.command({
         id: item.title,
       })
     }
   }
packages/nc-gui/components/smartsheet/grid/Table.vue (3)

855-856: Ensure safe casting of colOptions to ButtonType

When casting field?.colOptions to ButtonType, ensure that colOptions is not null or undefined to prevent runtime errors. Consider adding a type guard to confirm colOptions exists before casting.

Apply this diff to enhance type safety:

const field = fields.value[selectedRange.start.col]
return {
-  enabled: isAIPromptCol(field) || isAiButton(field),
-  disabled: !(field?.colOptions as ButtonType)?.fk_integration_id,
+  enabled: isAIPromptCol(field) || isAiButton(field),
+  disabled: !(field?.colOptions && (field.colOptions as ButtonType)?.fk_integration_id),
}

Line range hint 879-883: Validate colOptions before accessing output_column_ids

When accessing field.colOptions?.output_column_ids, ensure that colOptions is defined to avoid potential runtime errors. Adding a type check can improve robustness.

Consider modifying the code as follows:

if (isAiButton(field)) {
+ if (field.colOptions) {
    outputColumnIds =
      ncIsString(field.colOptions.output_column_ids) && field.colOptions.output_column_ids.split(',').length > 0
        ? field.colOptions.output_column_ids.split(',')
        : []
+ }
}

2146-2146: Correct the typo in method name expandAndLooseFocus

The method name expandAndLooseFocus contains a typo. It should be expandAndLoseFocus to use the correct spelling of "lose."

Apply this diff to fix the typo:

-const expandAndLooseFocus = (row: Row, col: Record<string, any>) => {
+const expandAndLoseFocus = (row: Row, col: Record<string, any>) => {

Also, update all references to this method within the component:

-@click="expandAndLooseFocus(row, state)"
+@click="expandAndLoseFocus(row, state)"
packages/nc-gui/composables/useIntegrationsStore.ts (2)

293-295: Simplify null checks using optional chaining

You can simplify the condition if (response && response?.id) by using optional chaining.

Apply this diff:

-        if (response && response?.id) {
+        if (response?.id) {

Line range hint 447-496: Add error handling to loadDynamicIntegrations function

Currently, loadDynamicIntegrations does not handle potential errors from the API call. Consider adding error handling to manage exceptions and provide user feedback if the API request fails.

Apply this change:

 const loadDynamicIntegrations = async () => {
   if (integrationsInitialized.value) return

   integrationsInitialized.value = true

-  const dynamicIntegrations = (await $api.integrations.list()) as {
+  try {
+    const dynamicIntegrations = (await $api.integrations.list()) as {
       type: IntegrationsType
       subType: string
       meta: {
         title?: string
         icon?: string
         description?: string
         order?: number
       }
     }[]

     dynamicIntegrations.sort((a, b) => (a.meta.order ?? Infinity) - (b.meta.order ?? Infinity))

     for (const di of dynamicIntegrations) {
       // existing logic
     }
+  } catch (e) {
+    await message.error('Failed to load dynamic integrations.')
+    console.error(e)
+  }
 }

This addition ensures that any errors during the API call are caught and handled appropriately.

packages/nc-gui/components/smartsheet/grid/InfiniteTable.vue (3)

Line range hint 10-16: Add missing import for isAiButton

The function isAiButton is used in the code but not imported, which will lead to a runtime error. Please import isAiButton from the appropriate module to ensure the code functions correctly.

Apply this diff to add the missing import:

 import {
   type ButtonType,
   type ColumnReqType,
   type ColumnType,
   type TableType,
   UITypes,
   type ViewType,
   ViewTypes,
+  isAiButton,
   isAIPromptCol,
   isCreatedOrLastModifiedByCol,
   isCreatedOrLastModifiedTimeCol,
   isLinksOrLTAR,
   isSystemColumn,
   isVirtualCol,
 } from 'nocodb-sdk'

2249-2255: Correct the typo in method name expandAndLooseFocus

The method name expandAndLooseFocus contains a typo. It should be expandAndLoseFocus to use the correct spelling of "lose". Please consider renaming the method and updating all references accordingly.

Apply these diffs to fix the typo:

In the method definition:

-const expandAndLooseFocus = (row: Row, col: Record<string, any>) => {
+const expandAndLoseFocus = (row: Row, col: Record<string, any>) => {
   if (expandForm) {
     expandForm(row, col)
   }
   // remove focus from the cell
   activeCell.row = null
   activeCell.col = null
   selectedRange.clear()
 }

In the method usage:

-    @click="expandAndLooseFocus(row, state)"
+    @click="expandAndLoseFocus(row, state)"

2249-2249: Specify ring size in active:ring class

In Tailwind CSS, the ring utility class should specify a ring width, such as ring-1, ring-2, etc. The class active:ring may not apply any ring without a size specified. Please specify a ring size to ensure the ring effect works as intended.

Apply this diff to fix the class:

-class="cursor-pointer flex items-center border-1 border-gray-100 active:ring rounded-md p-1 hover:(bg-white border-nc-border-gray-medium)"
+class="cursor-pointer flex items-center border-1 border-gray-100 active:ring-2 rounded-md p-1 hover:(bg-white border-nc-border-gray-medium)"
packages/nc-gui/components/smartsheet/column/LongTextOptions.vue (5)

41-42: Correct typo in variable name isFieldAddedInPromt

The variable isFieldAddedInPromt contains a typo. It should be isFieldAddedInPrompt for clarity and consistency.

Apply this diff to fix the typo:

-const isFieldAddedInPromt = availableFields.value.some((f) => {
+const isFieldAddedInPrompt = availableFields.value.some((f) => {

126-140: Simplify the handleDisableSubmitBtn function logic

The handleDisableSubmitBtn function can be streamlined to improve readability and reduce complexity.

Refactor the function as follows:

const handleDisableSubmitBtn = () => {
-  if (!isEnabledGenerateText.value) {
-    if (disableSubmitBtn.value) {
-      disableSubmitBtn.value = false
-    }
-    return
-  }
-
-  if (isPreviewEnabled.value) {
-    disableSubmitBtn.value = false
-  } else {
-    disableSubmitBtn.value = true
-  }
+  if (!isEnabledGenerateText.value || isPreviewEnabled.value) {
+    disableSubmitBtn.value = false
+  } else {
+    disableSubmitBtn.value = true
+  }
}

74-75: Improve the error message for better user clarity

The current error message could be more user-friendly and grammatically correct.

Apply this diff to update the error message:

-message.error('Include at least 1 sample record in table to generate')
+message.error('Please include at least one sample record in the table to generate.')

108-109: Add a null check for column?.value?.colOptions before accessing prompt_raw

To prevent potential undefined errors, ensure that colOptions exists before accessing prompt_raw.

Update the assignment as follows:

-vModel.value.prompt_raw = (column?.value?.colOptions as Record<string, any>)?.prompt_raw || ''
+vModel.value.prompt_raw = ((column?.value?.colOptions as Record<string, any>)?.prompt_raw) || ''

Alternatively, if colOptions might be undefined:

-vModel.value.prompt_raw = (column?.value?.colOptions as Record<string, any>)?.prompt_raw || ''
+vModel.value.prompt_raw = (column?.value?.colOptions && (column.value.colOptions as Record<string, any>).prompt_raw) || ''

112-113: Ensure colOptions exists before accessing fk_integration_id

To prevent undefined access, check if colOptions is available when assigning fk_integration_id.

Update the code as follows:

-if (isEdit.value) {
-  vModel.value.fk_integration_id = vModel.value?.colOptions?.fk_integration_id
+if (isEdit.value && vModel.value?.colOptions?.fk_integration_id) {
+  vModel.value.fk_integration_id = vModel.value.colOptions.fk_integration_id
}
packages/nc-gui/components/cell/TextArea.vue (4)

Line range hint 426-439: Internationalization: Localize Hardcoded Strings

The hardcoded strings "Record Data Updated" and "Cell values in this record have been updated. Regenerate to get more accurate content." should be localized to support internationalization. Use the $t function for translations.

Apply this diff to localize the strings:

 <div class="flex flex-col">
-  <div class="font-bold text-small leading-[18px] text-nc-content-gray">Record Data Updated</div>
-  <div class="text-small leading-[18px] text-nc-content-gray-muted">
-    Cell values in this record have been updated. Regenerate to get more accurate content.
-  </div>
+  <div class="font-bold text-small leading-[18px] text-nc-content-gray">{{ $t('message.recordDataUpdated') }}</div>
+  <div class="text-small leading-[18px] text-nc-content-gray-muted">
+    {{ $t('message.cellValuesUpdated') }}
+  </div>
 </div>

Line range hint 439-484: Internationalization: Localize Hardcoded Strings

Strings like "Generated by AI", "Edited by you", and "Re-generate" are hardcoded. For internationalization support, wrap these strings with the $t function.

Apply this diff to localize the strings:

- <span class="text-nc-content-purple-light truncate">Generated by AI</span>
+ <span class="text-nc-content-purple-light truncate">{{ $t('message.generatedByAI') }}</span>

- <template #title> Edited by you </template>
+ <template #title>{{ $t('message.editedByYou') }}</template>

- <template #loading> Re-generating... </template>
+ <template #loading>{{ $t('button.reGenerating') }}</template>

- Re-generate
+ {{ $t('button.reGenerate') }}

Line range hint 655-666: Avoid Code Duplication: Extract Warning into a Reusable Component

The "Record Data Updated" warning message is duplicated in lines 426-439 and 655-666. Extracting this into a reusable component will enhance maintainability and reduce redundancy.


726-726: Ensure CSS Compatibility and Specificity

The use of @apply !flex cursor-pointer; may cause issues with CSS specificity or browser compatibility. Ensure that the utilities used are supported across your target browsers and consider alternative methods if necessary.

packages/nocodb/src/models/AIColumn.ts (2)

26-26: Consider replacing 'this' with the class name in static methods for clarity.

In static methods, using this can be confusing since it refers to the class itself. It's clearer to use the class name directly. Replace this with AIColumn to improve readability.

Apply this diff to make the change:

-      return this._insert(
+      return AIColumn._insert(
🧰 Tools
🪛 Biome (1.9.4)

[error] 26-26: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


40-40: Consider replacing 'this' with the class name in static methods for clarity.

Similarly, replace this with AIColumn in the update method for consistency and clarity.

Apply this diff to make the change:

-      return this._update(
+      return AIColumn._update(
🧰 Tools
🪛 Biome (1.9.4)

[error] 40-40: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

packages/nocodb/src/models/LongTextColumn.ts (2)

61-61: Consider replacing 'this' with the class name in static methods for clarity.

Using this in static methods can be confusing. Replace this with LongTextColumn to enhance readability.

Apply this diff:

-        return this.read(context, longTextColumn.fk_column_id, ncMeta);
+        return LongTextColumn.read(context, longTextColumn.fk_column_id, ncMeta);
🧰 Tools
🪛 Biome (1.9.4)

[error] 61-61: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


85-85: Consider replacing 'this' with the class name in static methods for clarity.

Replace this with LongTextColumn in the read method to maintain consistency and improve clarity.

Apply this diff:

-        return column ? this.castType(column) : null;
+        return column ? LongTextColumn.castType(column) : null;
🧰 Tools
🪛 Biome (1.9.4)

[error] 85-85: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

packages/nc-gui/components/smartsheet/column/EditOrAdd.vue (1)

1098-1104: Refactor nested ternary operators for better readability

The nested ternary operators in the template make the code hard to read and maintain:

<component
  :is="
    isAiButtonSelectOption(opt.name) && !isColumnTypeOpen
      ? iconMap.cellAiButton
      : isAiPromptSelectOption(opt.name) && !isColumnTypeOpen
      ? iconMap.cellAi
      : opt.icon
  "
  ...
/>

Consider refactoring this logic into a computed property or a separate function for clarity:

<component :is="getOptionIcon(opt.name)" ... />
const getOptionIcon = (uidt) => {
  if (isAiButtonSelectOption(uidt) && !isColumnTypeOpen.value) {
    return iconMap.cellAiButton;
  } else if (isAiPromptSelectOption(uidt) && !isColumnTypeOpen.value) {
    return iconMap.cellAi;
  } else {
    return opt.icon;
  }
};
packages/nocodb/src/db/conditionV2.ts (1)

Line range hint 921-921: Use optional chaining to prevent potential runtime errors

The condition if (ai.prompt && ai.prompt.match(/{column_id}/)) can be simplified using optional chaining to prevent a potential TypeError if ai.prompt is undefined or null.

Apply this diff to use optional chaining:

-if (ai.prompt && ai.prompt.match(/{column_id}/)) {
+if (ai.prompt?.match(/{column_id}/)) {
packages/nocodb/src/models/Column.ts (1)

886-926: Use optional chaining to prevent potential runtime errors

In the delete method, the condition if (ai.prompt && ai.prompt.match(/{column_id}/)) should use optional chaining to avoid a potential TypeError if ai.prompt is undefined or null.

Apply this diff to use optional chaining:

-if (ai.prompt && ai.prompt.match(/{column_id}/)) {
+if (ai.prompt?.match(/{column_id}/)) {
🧰 Tools
🪛 Biome (1.9.4)

[error] 921-921: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

packages/nocodb/src/services/columns.service.ts (1)

1578-1646: Add error handling for data conversion during AI prompt column updates

The logic for converting data when updating AI prompt columns is sound. However, consider adding error handling to manage potential issues during the conversion process, such as unexpected data formats or exceptions thrown by the conversion functions.

packages/nocodb/src/db/BaseModelSqlv2.ts (3)

13-19: Group and Organize Imports for Clarity

Consider grouping related imports together and removing any unused imports to enhance readability and maintainability.


9779-9780: Update Method Documentation for prepareNocoData

The method signature of prepareNocoData has been updated to include an optional extra parameter. Ensure the method's documentation is updated to reflect this change and describe the purpose of the new parameter.


10063-10104: Avoid Mutating Parameters Directly

In the prepareNocoData method, the value variable is reassigned after checking its type. To prevent unintended side effects, consider using a new variable instead of reassigning value.

Apply this diff:

            if (data[column.column_name]) {
-             let value = data[column.column_name];
+             const originalValue = data[column.column_name];
+             let value;
              
-             if (typeof value === 'object') {
-               value = value.value;
+             if (typeof originalValue === 'object') {
+               value = originalValue.value;
              } else {
-               value = value;
+               value = originalValue;
              }
packages/nocodb/src/meta/migrations/v2/nc_069_ai_prompt.ts (2)

4-4: Add Documentation for Migration Functions

Consider adding JSDoc comments for the up and down functions to explain their purpose and usage. This will improve code readability and maintainability.


21-21: Consider Indexing Additional Columns for Performance

Currently, only fk_column_id is indexed. If queries frequently filter by other columns like fk_model_id or fk_workspace_id, consider adding indexes to those columns to enhance query performance.

packages/nc-gui/components/general/Loader.vue (2)

4-7: Set Default Values for Optional Props

The size and loaderClass props are optional. Consider providing default values to ensure consistent behavior when these props are not supplied.

You can use withDefaults to set default prop values:

const props = withDefaults(defineProps<GeneralLoaderProps>(), {
  size: 'medium',
  loaderClass: '',
});

9-9: Validate Prop Types to Ensure Correct Usage

The size prop accepts specific string literals or a number. To enforce valid prop values at runtime, consider adding Vue's validator function or using runtime prop validation.

Example:

const props = defineProps({
  size: {
    type: [String, Number],
    default: 'medium',
    validator: (value) => ['small', 'medium', 'large', 'xlarge', 'regular'].includes(value) || typeof value === 'number',
  },
  loaderClass: {
    type: String,
    default: '',
  },
});
packages/nocodb-sdk/src/lib/index.ts (1)

15-15: Maintain Alphabetical Order in Export Statements

For better readability and maintenance, consider arranging the exports in alphabetical order or logical groupings.

packages/nocodb/src/models/index.ts (1)

51-52: Arrange Exports Alphabetically for Consistency

To enhance readability, place the exports in alphabetical order within the list.

Apply this diff:

+ export { default as AIColumn } from './AIColumn';
...
- export { default as AIColumn } from './AIColumn';

Ensure that AIColumn and LongTextColumn are positioned appropriately.

packages/nocodb-sdk/src/lib/helperFunctions.ts (2)

231-237: Improve type safety of parseHelper function.

While the implementation is correct, we can improve type safety.

Consider this improvement:

- export function parseHelper(v: any): any {
+ export function parseHelper<T = any>(v: string | T): T {
  try {
-   return typeof v === 'string' ? JSON.parse(v) : v;
+   return typeof v === 'string' ? (JSON.parse(v) as T) : v;
  } catch {
    return v as T;
  }
}

239-244: Improve type safety of stringifyHelper function.

The implementation can be enhanced with better typing.

Consider this improvement:

- export function stringifyHelper(v: any): string {
+ export function stringifyHelper<T>(v: T): string {
  try {
    return JSON.stringify(v);
  } catch {
-   return v;
+   return String(v);
  }
}
packages/nc-gui/components/ai/PromptWithFields.vue (1)

161-178: Consider memory optimization for tooltip instances

The tooltip implementation could be optimized to prevent potential memory leaks:

  1. Consider using a WeakMap to store tooltip instances
  2. Add error handling for tooltip creation
-const tooltipInstances: any[] = []
+const tooltipInstances = new WeakMap()

 function loadMentionFieldTagTooltip() {
   document.querySelectorAll('.nc-ai-prompt-with-fields .prompt-field-tag').forEach((el) => {
     const tooltip = Object.values(el.attributes).find((attr) => attr.name === 'data-tooltip')
     if (!tooltip || el.scrollWidth <= el.clientWidth) return
-    const instance = tippy(el, {
-      content: `<div class="tooltip text-xs">${tooltip.value}</div>`,
-      placement: 'top',
-      allowHTML: true,
-      arrow: true,
-      animation: 'fade',
-      duration: 0,
-      maxWidth: '200px',
-    })
-    tooltipInstances.push(instance)
+    try {
+      const instance = tippy(el, {
+        content: `<div class="tooltip text-xs">${tooltip.value}</div>`,
+        placement: 'top',
+        allowHTML: true,
+        arrow: true,
+        animation: 'fade',
+        duration: 0,
+        maxWidth: '200px',
+      })
+      tooltipInstances.set(el, instance)
+    } catch (error) {
+      console.error('Failed to create tooltip:', error)
+    }
   })
 }
packages/nc-gui/components/smartsheet/header/Cell.vue (1)

46-54: Consider extracting type detection logic

The column type detection logic could be extracted into a utility function for better maintainability and reusability.

+const getColumnTypeName = (column: ColumnType) => {
+  if (column.uidt === UITypes.LongText) {
+    if (parseProp(column?.meta)?.richMode) {
+      return UITypesName.RichText
+    }
+    if (parseProp(column?.meta)?.[LongTextAiMetaProp]) {
+      return UITypesName.AIPrompt
+    }
+  }
+  return column.uidt ? UITypesName[column.uidt] : ''
+}

 const columnTypeName = computed(() => {
-  if (column.value.uidt === UITypes.LongText) {
-    if (parseProp(column.value?.meta)?.richMode) {
-      return UITypesName.RichText
-    }
-    if (parseProp(column.value?.meta)?.[LongTextAiMetaProp]) {
-      return UITypesName.AIPrompt
-    }
-  }
-  return column.value.uidt ? UITypesName[column.value.uidt] : ''
+  return getColumnTypeName(column.value)
 })
packages/nc-gui/components/smartsheet/PlainCell.vue (1)

207-211: Verify AI prompt value extraction

The implementation correctly handles AI prompt columns by extracting the value property from the AIRecordType. However, we should ensure proper null checking.

Consider adding null checking:

  if (isAIPromptCol(col)) {
-    return (modelValue as AIRecordType)?.value || ''
+    return modelValue ? (modelValue as AIRecordType)?.value || '' : ''
  }
packages/nc-gui/components/smartsheet/Cell.vue (1)

150-176: Excellent refactor: Centralized cell type determination

The new cellType computed property significantly improves code maintainability by:

  • Centralizing all cell type determination logic
  • Making the code more maintainable and easier to extend
  • Reducing duplicate type checking in the template

Consider extracting the cell type mapping to a separate constant:

const CELL_TYPE_MAPPING = {
  ai: isAI,
  textarea: isTextArea,
  // ... other mappings
} as const;
packages/nc-gui/components/workspace/project/AiCreateProject.vue (2)

150-164: Consider adding error handling for empty prompts

The prompt construction logic is well-implemented, but consider adding validation to ensure the base prompt is not empty before emitting the event.

 let prompt = `${aiFormState.value.prompt}`

+if (!prompt.trim()) {
+  return
+}

 // Append optional information if provided
 if (aiFormState.value.organization?.trim()) {
   prompt += ` | Organization: ${aiFormState.value.organization}`
 }

Line range hint 431-434: Consider reducing the delay duration

5 seconds might be too long for the copy feedback to persist. Consider reducing it to 2-3 seconds for better user experience.

-await ncDelay(5000)
+await ncDelay(2000)
packages/nocodb/src/modules/jobs/jobs/export-import/export.service.ts (1)

628-636: Consider adding error logging for JSON stringify failures

While the error handling for JSON stringify is implemented correctly, consider logging the error for debugging purposes.

 if (col.meta?.[LongTextAiMetaProp] && v) {
   try {
     row[colId] = JSON.stringify(v);
   } catch (e) {
+    this.debugLog(`Failed to stringify AI prompt value: ${e}`);
     row[colId] = v;
   }
 }
packages/nocodb/src/db/formulav2/formulaQueryBuilderv2.ts (1)

832-872: Well-structured database-specific JSON handling for AI text

The implementation correctly handles JSON value extraction for AI text fields across different database types (PostgreSQL, MySQL, SQLite, and MSSQL) with proper fallback for non-AI fields.

However, consider adding error handling for JSON parsing failures.

 if (col.meta?.[LongTextAiMetaProp] === true) {
+  try {
     if (knex.clientType() === 'pg') {
       aliasToColumn[col.id] = async (): Promise<any> => {
         return {
           builder: knex.raw(`TRIM('"' FROM (??::jsonb->>'value'))`, [
             col.column_name,
           ]),
         };
       };
     } // ... rest of the database specific handling
+  } catch (error) {
+    logger.error(`Error parsing AI text: ${error}`);
+    return Promise.resolve({ builder: col.column_name });
+  }
 }
packages/nc-gui/composables/useMultiSelect/index.ts (1)

292-300: Enhanced copy handling for AI text fields

The implementation correctly extracts values from AI text fields while maintaining the existing behavior for regular text.

Consider adding null check for better robustness.

 if (parseProp(columnObj.meta)?.[LongTextAiMetaProp] === true) {
   const aiCell: AIRecordType = (columnObj.title && rowObj.row[columnObj.title]) || null
 
-  if (aiCell) {
+  if (aiCell?.value !== undefined && aiCell?.value !== null) {
     textToCopy = aiCell.value
+  } else {
+    textToCopy = ''
   }
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 36d6403 and 58a8a11.

📒 Files selected for processing (72)
  • packages/nc-gui/components/ai/PromptWithFields.vue (8 hunks)
  • packages/nc-gui/components/ai/Settings.vue (9 hunks)
  • packages/nc-gui/components/cell/AI.vue (8 hunks)
  • packages/nc-gui/components/cell/TextArea.vue (11 hunks)
  • packages/nc-gui/components/cell/attachment/index.vue (1 hunks)
  • packages/nc-gui/components/general/IntegrationIcon.vue (1 hunks)
  • packages/nc-gui/components/general/Loader.vue (1 hunks)
  • packages/nc-gui/components/nc/Button.vue (6 hunks)
  • packages/nc-gui/components/nc/List/RecordItem.vue (1 hunks)
  • packages/nc-gui/components/nc/Switch.vue (2 hunks)
  • packages/nc-gui/components/smartsheet/Cell.vue (3 hunks)
  • packages/nc-gui/components/smartsheet/Gallery.vue (1 hunks)
  • packages/nc-gui/components/smartsheet/Kanban.vue (1 hunks)
  • packages/nc-gui/components/smartsheet/PlainCell.vue (2 hunks)
  • packages/nc-gui/components/smartsheet/column/AiButtonOptions.vue (6 hunks)
  • packages/nc-gui/components/smartsheet/column/ButtonOptions.vue (2 hunks)
  • packages/nc-gui/components/smartsheet/column/EditOrAdd.vue (8 hunks)
  • packages/nc-gui/components/smartsheet/column/LongTextOptions.vue (2 hunks)
  • packages/nc-gui/components/smartsheet/column/UITypesOptionsWithSearch.vue (2 hunks)
  • packages/nc-gui/components/smartsheet/details/Fields.vue (1 hunks)
  • packages/nc-gui/components/smartsheet/expanded-form/index.vue (1 hunks)
  • packages/nc-gui/components/smartsheet/grid/GroupByTable.vue (1 hunks)
  • packages/nc-gui/components/smartsheet/grid/InfiniteTable.vue (4 hunks)
  • packages/nc-gui/components/smartsheet/grid/Table.vue (4 hunks)
  • packages/nc-gui/components/smartsheet/header/Cell.vue (1 hunks)
  • packages/nc-gui/components/smartsheet/header/CellIcon.ts (1 hunks)
  • packages/nc-gui/components/smartsheet/header/Menu.vue (4 hunks)
  • packages/nc-gui/components/smartsheet/header/VirtualCell.vue (1 hunks)
  • packages/nc-gui/components/smartsheet/toolbar/ViewActionMenu.vue (1 hunks)
  • packages/nc-gui/components/virtual-cell/Button.vue (1 hunks)
  • packages/nc-gui/components/virtual-cell/HasMany.vue (1 hunks)
  • packages/nc-gui/components/virtual-cell/ManyToMany.vue (1 hunks)
  • packages/nc-gui/components/virtual-cell/components/ListItem.vue (1 hunks)
  • packages/nc-gui/components/workspace/integrations/ConnectionsTab.vue (0 hunks)
  • packages/nc-gui/components/workspace/integrations/IntegrationsTab.vue (2 hunks)
  • packages/nc-gui/components/workspace/integrations/forms/EditOrAddCommon.vue (1 hunks)
  • packages/nc-gui/components/workspace/integrations/forms/EditOrAddDatabase.vue (2 hunks)
  • packages/nc-gui/components/workspace/project/AiCreateProject.vue (2 hunks)
  • packages/nc-gui/composables/useColumnCreateStore.ts (2 hunks)
  • packages/nc-gui/composables/useData.ts (2 hunks)
  • packages/nc-gui/composables/useInfiniteData.ts (2 hunks)
  • packages/nc-gui/composables/useIntegrationsStore.ts (8 hunks)
  • packages/nc-gui/composables/useMultiSelect/index.ts (2 hunks)
  • packages/nc-gui/composables/useNocoAi.ts (3 hunks)
  • packages/nc-gui/helpers/parsers/parserHelpers.ts (2 hunks)
  • packages/nc-gui/helpers/tiptapExtensions/mention/FieldList.vue (3 hunks)
  • packages/nc-gui/nuxt.config.ts (3 hunks)
  • packages/nc-gui/utils/cell.ts (1 hunks)
  • packages/nc-gui/utils/columnUtils.ts (4 hunks)
  • packages/nc-gui/utils/commonUtils.ts (1 hunks)
  • packages/nocodb-sdk/src/lib/Api.ts (0 hunks)
  • packages/nocodb-sdk/src/lib/UITypes.ts (3 hunks)
  • packages/nocodb-sdk/src/lib/globals.ts (1 hunks)
  • packages/nocodb-sdk/src/lib/helperFunctions.ts (1 hunks)
  • packages/nocodb-sdk/src/lib/index.ts (1 hunks)
  • packages/nocodb/src/db/BaseModelSqlv2.ts (8 hunks)
  • packages/nocodb/src/db/conditionV2.ts (2 hunks)
  • packages/nocodb/src/db/formulav2/formulaQueryBuilderv2.ts (2 hunks)
  • packages/nocodb/src/db/sortV2.ts (2 hunks)
  • packages/nocodb/src/meta/migrations/XcMigrationSourcev2.ts (3 hunks)
  • packages/nocodb/src/meta/migrations/v2/nc_069_ai_prompt.ts (1 hunks)
  • packages/nocodb/src/models/AIColumn.ts (1 hunks)
  • packages/nocodb/src/models/Column.ts (9 hunks)
  • packages/nocodb/src/models/Integration.ts (3 hunks)
  • packages/nocodb/src/models/LongTextColumn.ts (1 hunks)
  • packages/nocodb/src/models/index.ts (1 hunks)
  • packages/nocodb/src/modules/jobs/jobs/export-import/duplicate.processor.ts (2 hunks)
  • packages/nocodb/src/modules/jobs/jobs/export-import/export.service.ts (4 hunks)
  • packages/nocodb/src/modules/jobs/jobs/export-import/import.service.ts (5 hunks)
  • packages/nocodb/src/services/columns.service.ts (4 hunks)
  • packages/nocodb/src/utils/dataConversion.ts (1 hunks)
  • packages/nocodb/src/utils/globals.ts (2 hunks)
💤 Files with no reviewable changes (2)
  • packages/nc-gui/components/workspace/integrations/ConnectionsTab.vue
  • packages/nocodb-sdk/src/lib/Api.ts
✅ Files skipped from review due to trivial changes (1)
  • packages/nocodb-sdk/src/lib/globals.ts
🧰 Additional context used
📓 Learnings (1)
packages/nc-gui/components/smartsheet/grid/GroupByTable.vue (1)
Learnt from: DarkPhoenix2704
PR: nocodb/nocodb#8781
File: packages/nc-gui/components/smartsheet/grid/GroupBy.vue:225-232
Timestamp: 2024-11-12T03:23:04.401Z
Learning: DarkPhoenix2704 prefers to keep code implementations that prioritize readability, even if an alternative might be more concise.
🪛 Biome (1.9.4)
packages/nc-gui/composables/useIntegrationsStore.ts

[error] 296-296: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

packages/nocodb/src/models/AIColumn.ts

[error] 26-26: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 40-40: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

packages/nocodb/src/models/Column.ts

[error] 921-921: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

packages/nocodb/src/models/LongTextColumn.ts

[error] 61-61: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 85-85: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

🔇 Additional comments (76)
packages/nc-gui/components/nc/Switch.vue (1)

45-47: LGTM! Enhanced visual feedback for disabled states.

The addition of opacity-60 class provides better visual indication of the disabled state, following common UI patterns. The changes are consistently applied to both placement options.

Also applies to: 72-74

packages/nc-gui/components/virtual-cell/ManyToMany.vue (1)

148-149: LGTM! Icon and styling changes align with UI consistency improvements.

The changes to the expand icon and its dimensions are consistent with similar updates in other components, maintaining a uniform appearance across the application.

packages/nc-gui/components/workspace/integrations/forms/EditOrAddCommon.vue (1)

2-2: LGTM! Good TypeScript practice.

Using import type for type-only imports is a TypeScript best practice as it ensures better tree-shaking and clearer code intentions.

packages/nc-gui/components/general/IntegrationIcon.vue (1)

5-5: LGTM! Making size optional improves component flexibility.

The change to make the size prop optional with a default value of 'sm' is a good improvement that:

  • Simplifies usage when the default size is desired
  • Maintains backward compatibility through the default value
  • Preserves type safety with the string literal union type
packages/nc-gui/components/smartsheet/toolbar/ViewActionMenu.vue (1)

Line range hint 1-489: Implementation looks good!

The component demonstrates:

  • Good TypeScript integration
  • Proper Vue 3 composition API usage
  • Well-documented solutions for known issues
  • Clean separation of concerns
  • Consistent error handling patterns
packages/nc-gui/utils/commonUtils.ts (1)

103-111: LGTM! Array handling is robust and safe

The implementation correctly handles array inputs with proper null safety and type checking.

packages/nc-gui/components/smartsheet/column/AiButtonOptions.vue (2)

369-369: LGTM: Prop addition follows Vue.js conventions

The new is-edit-column prop is well-named and correctly bound to the isEdit state.


471-475: LGTM: Tooltip implementation enhances accessibility

The tooltip implementation follows best practices by:

  • Only showing when text is truncated
  • Using semantic markup
  • Maintaining accessibility
packages/nc-gui/components/virtual-cell/HasMany.vue (1)

149-150: LGTM: Icon and styling changes look good!

The icon change from "expand" to "maximize" aligns with the broader effort to maintain visual consistency across components. The explicit height and width classes (h-3 w-3) provide better control over the icon's dimensions.

packages/nc-gui/components/smartsheet/column/UITypesOptionsWithSearch.vue (2)

129-129: LGTM! Consistent styling for AI-related types.

The styling is appropriately applied to both AI-related types, maintaining visual consistency.


23-23: LGTM! Verify AI feature flag behavior.

The filtering logic correctly handles both AI-related types (AIButton and AIPrompt), ensuring they're only shown when AI features are enabled.

Let's verify the feature flag implementation:

✅ Verification successful

LGTM! AI feature flag implementation is consistent.

The codebase shows consistent usage of FEATURE_FLAG.AI_FEATURES across components for controlling AI-related functionality. The filtering logic in UITypesOptionsWithSearch.vue correctly aligns with other implementations:

  • AI-related components (AIButton and AIPrompt) are consistently gated behind the feature flag
  • The feature flag check is used similarly in other Vue components for AI features
  • The types are properly defined in the SDK and utilized throughout the codebase
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify AI feature flag usage and consistency
# Look for other components that might need similar AI type filtering

# Search for AIButton/AIPrompt type checks
rg -t vue "AIButton|AIPrompt" --no-heading

# Search for AI feature flag usage
rg -t vue "AI_FEATURES" --no-heading

Length of output: 137


Script:

#!/bin/bash
# Search for AIButton/AIPrompt type checks without file type restriction
rg "AIButton|AIPrompt" --no-heading

# Search for AI feature flag usage
rg "AI_FEATURES" --no-heading

# Search for feature flag related files
fd "feature.*flag" -t f

Length of output: 6818

packages/nc-gui/components/smartsheet/column/ButtonOptions.vue (1)

Line range hint 212-224: LGTM! Appropriate default values for AI button type.

The default values are well-chosen to visually distinguish AI buttons while maintaining consistency with the application's design language. The light theme and purple color scheme align well with typical AI-related UI patterns.

packages/nc-gui/composables/useNocoAi.ts (3)

22-22: LGTM! Clean computed property implementation

The computed property provides a reactive way to check AI integration availability.


347-347: LGTM! Proper export of new functionality

The new method is correctly exported along with the required state.


20-20: Verify the impact of using Partial

The type change from IntegrationType[] to Partial<IntegrationType>[] makes the integration objects more flexible but potentially less type-safe. This could lead to runtime errors if code assumes certain properties are always present.

✅ Verification successful

Let me analyze the usage patterns from the search results to make a final determination:

  1. Property access patterns found:

    • Basic array operations: .length, .filter(), .map()
    • Properties accessed: id, title, is_default
    • Used in comparisons and array operations via ncIsArrayIncludes
    • Used in UI conditionals checking .length
  2. Integration object creation:

    • When creating new integrations, all required properties are set: id, title, is_default

Type change to Partial is safe and justified

The usage patterns show that the code handles the properties safely:

  • The most commonly accessed property is id, which is consistently present when objects are created
  • Array operations use safe methods that don't assume property existence
  • UI operations primarily check array length rather than assuming property existence
  • When new items are added to the array, all essential properties are properly initialized
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usage of aiIntegrations to verify property access patterns
rg -A 3 "aiIntegrations\." packages/nc-gui/

Length of output: 5533

packages/nc-gui/components/virtual-cell/Button.vue (1)

213-213: Verify design system consistency for border radius change

The border radius has been changed from rounded-lg to rounded-md. While this is a valid change, ensure it:

  • Aligns with your design system's border radius tokens
  • Maintains consistent visual hierarchy with other UI elements
  • Preserves sufficient target area for touch interactions (min 44x44px for touch targets per WCAG)
✅ Verification successful

Border radius change is consistent with design system

Based on the codebase analysis, the change from rounded-lg to rounded-md in Button.vue is consistent with the design system:

  • The codebase shows both rounded-md and rounded-lg are commonly used border radius tokens
  • For buttons specifically, rounded-md is the more common choice, appearing in many button-like components and interactive elements
  • The change maintains sufficient touch target size as the border radius doesn't affect the button's clickable area
  • The modification aligns with similar button implementations across the codebase, particularly in:
    • Command palette buttons
    • Toolbar buttons
    • Form action buttons
    • Modal buttons
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other rounded-lg/rounded-md usage to verify consistency
rg --type vue 'rounded-(lg|md)' packages/nc-gui/

Length of output: 78


Script:

#!/bin/bash
# Search for rounded-lg/rounded-md usage in all files under packages/nc-gui/
rg 'rounded-(lg|md)' packages/nc-gui/

Length of output: 66487

packages/nc-gui/components/smartsheet/header/VirtualCell.vue (1)

133-136: Verify the implementation of isAiButton function

The code introduces a new condition for AI button handling, but the isAiButton function is not visible in the imports. Please ensure that this function is properly defined and imported.

Let's verify the existence and implementation of the isAiButton function:

packages/nc-gui/components/workspace/integrations/IntegrationsTab.vue (2)

42-42: LGTM: Method import follows established patterns

The addition of loadDynamicIntegrations to the store imports follows the existing patterns and naming conventions.


216-217: Verify integration loading state handling

The component shows a loading state based on integrationListContainerWidth, but we should verify if this adequately covers the dynamic integrations loading phase.

✅ Verification successful

Let me gather more information about the loading state handling.


Loading state is properly handled for dynamic integrations

The loading state for dynamic integrations is already well-managed through isLoadingIntegrations in the store. The store maintains this state during integration operations, and the component has access to it. The initial concern about integrationListContainerWidth is unrelated to the dynamic loading state.

  • useIntegrationsStore.ts manages loading through isLoadingIntegrations ref
  • Loading state is properly set during integration operations
  • The component has access to the loading state via the store
  • loadDynamicIntegrations is correctly called on component mount and has initialization check
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for loading state handling in related integration components
# Look for loading state management patterns in integration-related files

# Search for loading state patterns in integration components
echo "Searching for loading state patterns in integration components..."
rg -l "isLoading|loading" --type vue

# Check for error handling patterns in integration store
echo "Checking error handling in integration store..."
rg "loadDynamicIntegrations" --type ts -A 5 -B 5

Length of output: 1973


Script:

#!/bin/bash
# Search for loading state patterns in Vue files with proper extension
echo "Searching for loading state patterns in integration components..."
rg -l "isLoading|loading" packages/nc-gui/components/workspace/integrations/

# Check the integration store for loading state management
echo "Checking integration store for loading state..."
rg "integrationsInitialized|isLoading|loading" packages/nc-gui/composables/useIntegrationsStore.ts -A 3 -B 3

# Check how the loadDynamicIntegrations is used in components
echo "Checking usage of loadDynamicIntegrations..."
rg "loadDynamicIntegrations" packages/nc-gui/components/ -A 3 -B 3

Length of output: 4270

packages/nc-gui/components/smartsheet/grid/GroupByTable.vue (1)

279-279: LGTM! Consider documenting the ESLint rule override.

The addition of the v-model:selected-all-records binding and its integration with the selectedAllRecords state is well-implemented. However, let's verify why the ESLint rule needs to be disabled.

✅ Verification successful

ESLint rule disable comment is safe to keep

The ESLint disable comment for vue/no-restricted-v-bind is necessary here as it's used for a valid two-way binding pattern (v-model:selected-all-records) on the Table component. The rule is likely triggered due to the custom event binding syntax, but this is a legitimate use case in Vue 3 for component communication.

Looking at the component implementation and ESLint configuration:

  • The binding is used for syncing the selection state between parent and child components
  • The Table component explicitly supports this prop as shown in its usage
  • No issues were found in the codebase related to this rule
  • The local ESLint configuration doesn't show any custom restrictions for this rule
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check why the ESLint rule is disabled and if it's necessary

# Search for ESLint configuration files
echo "Searching for ESLint config files..."
fd -e json -e js -e cjs -e yaml -e yml -g '*eslint*'

# Search for other occurrences of this rule
echo "Checking for other occurrences of this rule..."
rg -l "vue/no-restricted-v-bind"

# Check if there are any related discussions
echo "Checking for related discussions..."
gh issue list --search "vue/no-restricted-v-bind in:body,comments,title"

Length of output: 489


Script:

#!/bin/bash
# Let's check the ESLint configuration and the specific rule usage context

# Check the content of the ESLint config files in the project root
echo "Checking ESLint config content..."
fd -e json -e js -e cjs -e yaml -e yml -g '*eslint*' --max-depth 1 --exec cat {}

# Check the specific line and surrounding context where the rule is disabled
echo "Checking the rule usage context..."
rg -C 5 "vue/no-restricted-v-bind" packages/nc-gui/components/smartsheet/grid/GroupByTable.vue

# Check for any custom ESLint rules in the project
echo "Checking for custom ESLint rules..."
fd -e js -e ts rules --exec cat {} 2>/dev/null

Length of output: 1004


Script:

#!/bin/bash
# Let's check the Vue component to understand the v-bind usage

# Check the entire component content to understand the context
echo "Checking the component content..."
cat packages/nc-gui/components/smartsheet/grid/GroupByTable.vue

# Look for any ESLint config in the nc-gui package
echo "Checking package-level ESLint config..."
cat packages/nc-gui/.eslintrc* 2>/dev/null || echo "No package-level ESLint config found"

# Check for Vue-specific ESLint config
echo "Checking Vue-specific ESLint rules..."
rg -l "vue/no-restricted-v-bind" packages/nc-gui/ -g '.eslintrc*'

Length of output: 10812

packages/nc-gui/components/virtual-cell/components/ListItem.vue (2)

Line range hint 39-51: Well-implemented error handling for attachments.

The attachments computed property demonstrates good practices:

  • Proper TypeScript interface definition
  • Robust error handling with fallback
  • Handles both string and object data formats

162-162: LGTM: Icon replacement maintains functionality.

The replacement of MaximizeIcon with GeneralIcon using the 'maximize' icon name maintains the same visual functionality while potentially reducing bundle size by consolidating icon imports.

Let's verify the GeneralIcon component supports all icons used in this file:

✅ Verification successful

Based on the extensive search results showing GeneralIcon usage across the codebase, I can see that the component is widely used with various icon names including 'maximize', 'fileImage', 'plus', 'minus' and many others. The icon replacement in ListItem.vue appears to be using a standard icon name that is commonly used throughout the application.

Icon replacement is safe and consistent with codebase patterns

The change from MaximizeIcon to GeneralIcon with 'maximize' icon name follows the established pattern in the codebase where GeneralIcon is the standard icon component used across many components with consistent icon naming.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify GeneralIcon component supports all required icons
# Check for GeneralIcon component definition and its icon prop values

# Search for GeneralIcon component and its supported icons
rg -A 2 "export.*GeneralIcon" 

# Search for all icon usages in this component
rg "GeneralIcon.*icon=\"[^\"]+\"" "packages/nc-gui/components/virtual-cell/components/ListItem.vue"

Length of output: 443


Script:

#!/bin/bash
# Let's verify the GeneralIcon component's implementation and supported icons

# First, find the GeneralIcon component file
fd -e vue -e ts -e js GeneralIcon

# Then look for icon definitions or mappings
rg -l "icon.*=.*{" $(fd -e vue -e ts -e js GeneralIcon)

# Also search for any icon-related types or interfaces
ast-grep --pattern 'interface $_Props {
  $$$
  icon: $_;
  $$$
}'

Length of output: 246


Script:

#!/bin/bash
# Let's try a different approach to find GeneralIcon and its usage

# Find GeneralIcon component file
fd GeneralIcon

# Look for icon-related imports and definitions
rg -A 3 "GeneralIcon" --type vue --type ts --type js

# Search for icon prop definitions
rg -A 3 "icon.*:.*prop" --type vue --type ts

Length of output: 172


Script:

#!/bin/bash
# Let's try one final approach without file type flags

# Find GeneralIcon component
fd GeneralIcon

# Look for icon-related imports and definitions
rg -A 3 "GeneralIcon"

# Search for icon prop definitions
rg -A 3 "props:\s*{.*icon"

Length of output: 67208

packages/nc-gui/utils/columnUtils.ts (1)

299-312: Verify the type casting of col.colOptions to ButtonType

In the UITypes.LongText case, col.colOptions is cast to ButtonType. Ensure that this casting is appropriate, as LongText columns may not have options matching the ButtonType interface. Incorrect casting could lead to runtime errors or unintended behavior.

Consider defining a specific type for LongText column options if necessary, to accurately represent the properties used in this context.

packages/nc-gui/components/smartsheet/details/Fields.vue (1)

1040-1043: ⚠️ Potential issue

Add missing import for ncDelay function

The ncDelay function used at line 1042 is not defined or imported in this file, which will result in a ReferenceError.

Apply this diff to fix the issue:

+import { ncDelay } from '~/helpers/utils'
⛔ Skipped due to learnings
Learnt from: rameshmane7218
PR: nocodb/nocodb#9956
File: packages/nc-gui/components/smartsheet/details/Fields.vue:1041-1043
Timestamp: 2024-12-07T12:11:23.602Z
Learning: In the 'nc-gui' package, the function `ncDelay` is globally imported, making it available in Vue components without the need for explicit import statements.
packages/nc-gui/helpers/tiptapExtensions/mention/FieldList.vue (1)

59-64: 🛠️ Refactor suggestion

Review the timeout implementation in the '}' key handler

The current implementation has potential issues:

  1. The 250ms timeout seems arbitrary and could lead to race conditions
  2. The timeout isn't cleaned up if the component is destroyed
  3. It's inconsistent with other key handlers that execute immediately

Consider this alternative implementation:

 if (event.key === '}') {
-  setTimeout(() => {
-    this.selectItem(this.selectedIndex)
-  }, 250)
+  this.selectItem(this.selectedIndex)
+  return true
 }

If the timeout is absolutely necessary, implement proper cleanup:

 export default {
   data() {
     return {
       selectedIndex: 0,
+      keyTimeout: null,
     }
   },
+  beforeDestroy() {
+    if (this.keyTimeout) {
+      clearTimeout(this.keyTimeout)
+    }
+  },
   methods: {
     onKeyDown({ event }) {
       if (event.key === '}') {
-        setTimeout(() => {
+        if (this.keyTimeout) {
+          clearTimeout(this.keyTimeout)
+        }
+        this.keyTimeout = setTimeout(() => {
           this.selectItem(this.selectedIndex)
+          this.keyTimeout = null
         }, 250)
+        return true
       }
     }
   }
 }
packages/nc-gui/components/smartsheet/grid/Table.vue (1)

8-8: Added import of isAIPromptCol function

The isAIPromptCol function is imported correctly and ready for use within the component.

packages/nc-gui/composables/useIntegrationsStore.ts (1)

93-93: LGTM!

The addition of aiIntegrations from useNocoAi() aligns with the integration management logic.

packages/nc-gui/components/smartsheet/column/LongTextOptions.vue (2)

94-101: 🛠️ Refactor suggestion

Add null checks when accessing nested properties in res

When accessing res[0]?.[previewFieldTitle.value], ensure that res[0] and previewFieldTitle.value are not undefined to prevent potential runtime errors.

Consider updating the condition:

-if (res?.length && res[0]?.[previewFieldTitle.value]) {
+if (res?.length && res[0] && previewFieldTitle.value && res[0][previewFieldTitle.value]) {

Likely invalid or redundant comment.


85-89: Verify that LongTextAiMetaProp is defined

Ensure that LongTextAiMetaProp is properly defined and imported, as it's used in setting metadata.

Run the following script to check if LongTextAiMetaProp is defined:

packages/nc-gui/components/cell/TextArea.vue (1)

Line range hint 742-749: Verify the Usage of Experimental CSS Selector :has()

The :has() pseudo-class is currently an experimental feature and may not be supported in all browsers. Using it in:

&:has(.nc-cell-longtext-ai .nc-expanded-form-open) {
  @apply !border-none -mx-1 -my-1;
  box-shadow: none !important;
}

could lead to inconsistent styling across different user environments.

Run the following script to check browser compatibility:

✅ Verification successful

Since we cannot directly fetch browser compatibility data, let me check the project's configuration and dependencies to understand the build setup and browser targets.


Let me check the project's browser target configuration in the Nuxt config since this is a Vue/Nuxt project.


The :has() selector usage is safe in this codebase

The :has() selector is now widely supported in all major browsers (Chrome, Firefox, Safari, Edge) since late 2022, with global usage above 94%. In this codebase, it's being used appropriately for progressive enhancement scenarios:

  1. Most usages are for styling optimizations (like removing borders or shadows) that won't break functionality if not supported
  2. The selectors are used within SCSS/CSS modules which will be processed by PostCSS/autoprefixer
  3. The application is a modern web app (Nuxt 3) targeting modern browsers

The codebase's browser support is defined through its dependencies and build tools:

  • Uses modern Nuxt 3 framework
  • Employs Vue 3 and modern build tooling
  • Has no explicit legacy browser support requirements
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check browser compatibility for the `:has()` pseudo-class.

# Expected Result: List of browsers that support `:has()`.
echo "Checking CSS :has() browser compatibility..."
curl -s 'https://caniuse.com/css-has' | grep -A5 "Browser" | sed -n '/Browser Usage table/,/Feature/ p'

Length of output: 200


Script:

#!/bin/bash
# Check package.json and browserslist config
echo "=== Checking package.json ==="
fd package.json --exec cat {}

echo -e "\n=== Checking .browserslistrc ==="
fd .browserslistrc --exec cat {}

echo -e "\n=== Checking babel.config.js ==="
fd babel.config.js --exec cat {}

echo -e "\n=== Checking for postcss config ==="
fd "postcss.config.js" --exec cat {}

Length of output: 33837


Script:

#!/bin/bash
# Check Nuxt config for browser targets and PostCSS configuration
echo "=== Checking nuxt.config.ts ==="
fd "nuxt.config.ts" --exec cat {}

echo -e "\n=== Checking for CSS usage of :has() ==="
rg -g "*.{vue,css,scss}" ":has\(" --context 2

Length of output: 23455

packages/nocodb/src/db/conditionV2.ts (1)

596-613: Ensure correct JSON value extraction for AI prompt columns

The implementation correctly adjusts the field variable for AI prompt columns based on the database client type. This ensures that the 'value' field is properly extracted from the JSON structure across different databases.

packages/nocodb/src/models/Column.ts (2)

452-469: Correctly handle insertion of AI prompt options for LongText columns

The addition of the LongText case in the insertColOption method appropriately handles AI prompt columns by checking the metadata and inserting AI column options when necessary.


573-577: Proper retrieval of AI options for LongText columns

The getColOptions method correctly retrieves AI options for LongText columns when they are identified as AI prompt columns in the metadata.

packages/nocodb/src/modules/jobs/jobs/export-import/import.service.ts (3)

182-182: Appropriate exclusion of AI prompt columns during static column creation

The condition !isAIPromptCol(a) ensures that AI prompt columns are excluded from the initial creation of tables with static columns. This is appropriate as AI prompt columns may require special handling during import.


1113-1114: Correct inclusion of AI prompt columns in referenced columns

Including AI prompt columns in the referencedColumnSet ensures they are processed correctly during the import phase, accommodating their special requirements.


Line range hint 1244-1281: Verify the resetting of AI prompt column properties during import

When importing AI prompt columns, the properties fk_workspace_id, fk_integration_id, and model are set to null if the workspace IDs do not match. Confirm that this behavior is intended and that resetting these properties will not cause issues with AI integrations or data consistency.

Please ensure that resetting these properties does not lead to broken references or unexpected behavior in the application.

packages/nocodb/src/services/columns.service.ts (1)

2282-2304: Correct substitution of column aliases with IDs in AI prompts

When adding an AI prompt column, the code appropriately substitutes column aliases with their corresponding IDs in the prompt. This ensures that the prompt references are accurate and function as intended.

packages/nc-gui/components/smartsheet/header/CellIcon.ts (1)

23-24: LGTM! Verify icon asset availability.

The AI column type condition is correctly placed before the text area check.

Let's verify the icon asset exists:

✅ Verification successful

Let me gather more information about the icon definitions.


Let me check the actual icon definitions in the iconMap.


Let me check for the specific cellAi icon definition in the iconUtils file.


Icon asset is properly defined and available

The cellAi icon is correctly defined in iconUtils.ts and mapped to the NcCellAi component with appropriate styling. The code change is safe to use.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for cellAi icon definition
rg -g '!*.{lock,min.js,map}' 'cellAi.*=.*' .

Length of output: 187


Script:

#!/bin/bash
# Search for icon definitions in iconMap or similar structures
rg -g '!*.{lock,min.js,map}' 'iconMap.*cellAi' .

# Also search for any cellAi related icon definitions
rg -g '!*.{lock,min.js,map}' 'cellAi.*icon' .

# Look for icon mapping files
fd -e ts -e js -e vue icon

Length of output: 2002


Script:

#!/bin/bash
# Look for iconMap definition file and its contents
rg -g '!*.{lock,min.js,map}' 'const.*iconMap.*=' -A 10 .

Length of output: 3194


Script:

#!/bin/bash
# Look for cellAi related icon definitions in iconUtils.ts
rg -g '!*.{lock,min.js,map}' 'cellAi' ./packages/nc-gui/utils/iconUtils.ts

Length of output: 186

packages/nocodb/src/utils/globals.ts (1)

15-15: Verify the impact of enum changes across the codebase

The replacement of COL_AI with COL_LONG_TEXT in both MetaTable and CacheScope enums needs careful verification to ensure all references are updated.

Also applies to: 148-148

✅ Verification successful

Based on the code analysis, I can now generate the final response:

No impact from COL_LONG_TEXT enum changes

The changes to COL_LONG_TEXT in both MetaTable and CacheScope enums are safe and do not require any further verification. The code shows that:

  1. COL_LONG_TEXT is used consistently in both enums for long text column metadata storage and caching
  2. The implementation in LongTextColumn.ts correctly uses these enum values
  3. No direct references to COL_AI exist in the codebase, indicating this is a new addition rather than a replacement
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for any remaining references to COL_AI that might have been missed

# Check for any remaining COL_AI references
echo "Checking for remaining COL_AI references..."
rg "COL_AI" --type ts --type vue

# Check current usage of new COL_LONG_TEXT
echo "Checking current COL_LONG_TEXT usage..."
rg "COL_LONG_TEXT" --type ts --type vue

Length of output: 314


Script:

#!/bin/bash
# Let's try again with correct file extensions and more context

# Check for any remaining COL_AI references
echo "Checking for remaining COL_AI references..."
rg "COL_AI" -t typescript -t js -A 2 -B 2

# Check current usage of new COL_LONG_TEXT
echo "Checking current COL_LONG_TEXT usage..."
rg "COL_LONG_TEXT" -t typescript -t js -A 2 -B 2

# Also check for enum references in a case-insensitive manner
echo "Checking for case-insensitive references..."
rg -i "col_ai|col_long_text" -t typescript -t js --files-with-matches

Length of output: 550


Script:

#!/bin/bash
# Let's try with simpler ripgrep commands without file type specifications

# Check for any remaining COL_AI references
echo "Checking for remaining COL_AI references..."
rg "COL_AI" -A 2 -B 2 "*.ts"

# Check current usage of new COL_LONG_TEXT
echo "Checking current COL_LONG_TEXT usage..."
rg "COL_LONG_TEXT" -A 2 -B 2 "*.ts"

# Also check file names that might contain these terms
echo "Checking files containing these terms..."
fd -e ts -e js | xargs rg -l "COL_AI|COL_LONG_TEXT"

Length of output: 705


Script:

#!/bin/bash
# Let's examine the content of these files to understand the usage

echo "Checking globals.ts for context..."
cat packages/nocodb/src/utils/globals.ts

echo -e "\nChecking Column.ts for usage..."
cat packages/nocodb/src/models/Column.ts

echo -e "\nChecking LongTextColumn.ts..."
cat packages/nocodb/src/models/LongTextColumn.ts

echo -e "\nChecking migration file..."
cat packages/nocodb/src/meta/migrations/v2/nc_069_ai_prompt.ts

Length of output: 66846

packages/nocodb/src/db/sortV2.ts (2)

1-1: LGTM: Import statement is correctly placed

The import of isAIPromptCol is appropriately placed with related imports.


202-228: LGTM: Database-specific JSON handling is well implemented

The implementation correctly handles JSON extraction for different database types:

  • PostgreSQL using jsonb->>'value'
  • MySQL using JSON_EXTRACT and JSON_UNQUOTE
  • SQLite using json_extract
  • MSSQL using JSON_VALUE

The fallback to standard column sorting for non-AI columns is also properly implemented.

packages/nc-gui/components/nc/Button.vue (2)

4-4: LGTM: Props implementation follows best practices

The addition of the loaderSize prop with proper typing and default value follows Vue.js best practices and maintains type safety.

Also applies to: 23-23, 37-37


118-118: LGTM: Loader size customization properly implemented

The loaderSize prop is correctly bound to both instances of the GeneralLoader component, maintaining consistency in the loading state presentation.

Also applies to: 137-137

packages/nc-gui/components/ai/PromptWithFields.vue (2)

19-19: LGTM: Proper implementation of readOnly prop

The readOnly prop is correctly implemented with proper typing and default value.

Also applies to: 31-31


194-211: LGTM: Proper visual feedback for readonly state

The button and icon properly reflect the readonly state through disabled attribute and opacity changes.

packages/nc-gui/components/ai/Settings.vue (2)

170-180: LGTM: Improved select component implementation

The select component properly handles the model type changes and includes helpful placeholders for better UX.


Line range hint 70-86: Consider edge case handling in initialization logic

The initialization logic skips when isEditColumn is true, but there might be cases where model initialization is still needed even in edit mode.

packages/nc-gui/nuxt.config.ts (1)

229-230: Verify security implications and bundle size impact of new dependencies

The addition of new dependencies, particularly crossoriginworker, requires careful consideration:

  1. Ensure crossoriginworker follows secure cross-origin practices
  2. Consider lazy loading monaco-editor language support to reduce initial bundle size
  3. Verify if vue-barcode-reader can be dynamically imported only when needed

Also applies to: 242-242, 258-258

✅ Verification successful

Let me verify the usage patterns of these dependencies to better assess their impact.


Based on the results, I can now verify the security and bundle size implications:

Dependencies have minimal impact and no known security issues

  1. No security vulnerabilities found for crossoriginworker in GitHub's security database
  2. Bundle sizes are very small:
    • crossoriginworker: 469 bytes gzipped
    • vue-barcode-reader: 352 bytes gzipped
  3. Usage patterns show:
    • crossoriginworker is only used in worker utilities (workerUtils.ts)
    • vue-barcode-reader is used in form and QR scanner components
    • Both dependencies are properly scoped to their specific features
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for known vulnerabilities in new dependencies
gh api graphql -f query='
{
  securityVulnerabilities(first: 5, ecosystem: NPM, package: "crossoriginworker") {
    nodes {
      advisory {
        summary
        severity
      }
      vulnerableVersionRange
    }
  }
}
'

# Check bundle size impact
curl -s "https://bundlephobia.com/api/size?package=crossoriginworker" | jq '.gzip'
curl -s "https://bundlephobia.com/api/size?package=vue-barcode-reader" | jq '.gzip'

Length of output: 450


Script:

#!/bin/bash
# Check how crossoriginworker is used
rg -l "crossoriginworker" --type ts --type vue

# Check how vue-barcode-reader is used
rg -l "vue-barcode-reader" --type ts --type vue

# Check for dynamic imports
rg "import\(.+?['\"]vue-barcode-reader['\"]" --type ts --type vue
rg "import\(.+?['\"]monaco-editor" --type ts --type vue

# Check if dayjs/utc is used conditionally
rg "dayjs/plugin/utc" --type ts --type vue

Length of output: 409


Script:

#!/bin/bash
# Check usage patterns without file type restrictions
rg -l "crossoriginworker"

# Check how vue-barcode-reader is used
rg -l "vue-barcode-reader"

# Check for dynamic imports
rg "import\(.+?['\"]vue-barcode-reader['\"]"
rg "import\(.+?['\"]monaco-editor"

# Check if dayjs/utc is used conditionally
rg "dayjs/plugin/utc"

# List all .vue files to understand the correct extension
fd "\\.vue$"

Length of output: 66599

packages/nocodb-sdk/src/lib/UITypes.ts (1)

94-94: LGTM: New AI types added

The addition of AIPrompt to UITypesName is consistent with the existing pattern.

packages/nc-gui/components/nc/List/RecordItem.vue (1)

145-145: LGTM: Improved consistency in row data access

The change to use currentRow instead of directly accessing the row prop aligns better with Vue's reactivity system and maintains consistency with other parts of the component.

packages/nc-gui/components/smartsheet/PlainCell.vue (1)

3-3: LGTM: Type import added for AI functionality

The AIRecordType import is correctly added to support the new AI prompt column feature.

packages/nc-gui/components/smartsheet/Cell.vue (1)

212-263: Clean template refactor using cellType

The template has been effectively simplified using the new cellType computed property. The conditional rendering is now more maintainable and easier to understand.

packages/nocodb/src/meta/migrations/XcMigrationSourcev2.ts (1)

58-58: Migration added for AI prompt functionality

The new migration nc_069_ai_prompt is properly integrated:

  • Import statement added
  • Migration name added to the list
  • Switch case handler added

Let's verify the migration file exists:

Also applies to: 125-125, 249-250

✅ Verification successful

Migration file is properly structured and implements required functionality

The migration file exists and contains proper implementation:

  • Exports required up and down functions
  • Creates table COL_LONG_TEXT with appropriate columns for AI prompt functionality
  • Includes proper typing and follows the migration pattern
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if the migration file exists
fd "nc_069_ai_prompt.ts" --type f

Length of output: 92


Script:

#!/bin/bash
# Check the content of the migration file to verify it's properly structured
cat packages/nocodb/src/meta/migrations/v2/nc_069_ai_prompt.ts

Length of output: 791

packages/nc-gui/components/cell/attachment/index.vue (1)

427-427: LGTM: Icon update for better visual consistency

The change from iconMap.expand to iconMap.maximize aligns with modern UI conventions and maintains visual consistency across the application.

packages/nc-gui/composables/useColumnCreateStore.ts (2)

3-3: LGTM: Added AI prompt column detection utility

Added import of isAIPromptCol from nocodb-sdk to support AI prompt column detection.


113-116: LGTM: Enhanced AI mode detection

Added support for detecting AI prompt columns in addition to AI button actions, improving the accuracy of AI feature detection.

packages/nc-gui/helpers/parsers/parserHelpers.ts (3)

1-1: LGTM: Added UI type name constants

Added import of UITypesName to use standardized names for AI-related columns.


481-484: LGTM: Standardized AI button naming

Updated the AI button column naming to use the standardized UITypesName.AIButton constant.


486-490: LGTM: Added AI prompt column naming

Added support for generating standardized names for AI prompt columns using UITypesName.AIPrompt.

Let's verify the consistency of AI prompt column naming:

✅ Verification successful

AI prompt column naming implementation is consistent across the codebase

The verification shows consistent usage of UITypesName.AIPrompt for column naming and LongTextAiMetaProp for AI prompt detection:

  • Column naming: UITypesName.AIPrompt is used in both parserHelpers.ts and Cell.vue for standardized naming
  • AI prompt detection: LongTextAiMetaProp is consistently used as a metadata flag across the codebase
  • Implementation is properly integrated in key components:
    • Column services (columns.service.ts)
    • Model handling (Column.ts)
    • UI components (LongTextOptions.vue, Cell.vue)
    • Export/import functionality (export.service.ts)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistent usage of AI prompt column naming

# Search for AI prompt column name usage
rg -A 2 "UITypesName.AIPrompt"

# Search for LongTextAiMetaProp usage
rg -A 2 "LongTextAiMetaProp"

Length of output: 7299

packages/nocodb/src/models/Integration.ts (1)

454-457: LGTM: Defensive initialization of config.models array

Good addition of null check and array initialization. This prevents potential runtime errors when accessing config.models.

packages/nocodb/src/modules/jobs/jobs/export-import/duplicate.processor.ts (1)

4-9: LGTM: Added AI prompt column handling

Good addition of the AI prompt column check alongside virtual columns. This prevents unintended modifications of default values for AI-related columns.

Also applies to: 443-443

packages/nc-gui/components/smartsheet/Gallery.vue (1)

376-376: LGTM: Updated expand icon for consistency

Good update to use the maximize icon, maintaining visual consistency across the application.

packages/nc-gui/components/workspace/project/AiCreateProject.vue (1)

31-32: LGTM: Event tracking setup

The Nuxt app instance is correctly initialized for event tracking purposes.

packages/nc-gui/components/smartsheet/header/Menu.vue (2)

48-61: LGTM: Well-structured column validation

The column validation logic is well-implemented with proper null checks and comprehensive validation state handling.


451-451: LGTM: Consistent UI updates

The UI changes maintain consistency while adding proper error state handling and dynamic tooltips.

Also applies to: 461-461, 464-464

packages/nc-gui/composables/useData.ts (1)

2-2: LGTM: Proper AI prompt column handling

The AI prompt column handling is correctly integrated into the existing column update logic, following the established patterns for special column types.

Also applies to: 289-289

packages/nocodb/src/modules/jobs/jobs/export-import/export.service.ts (3)

146-155: LGTM: Column options handling looks good

The preservation of workspace-scoped values (fk_model_id, fk_workspace_id, fk_integrations_id, model) during export is correctly implemented.


156-160: LGTM: Output column IDs mapping is correct

The implementation properly maintains referential integrity by mapping IDs through idMap before joining.


180-181: LGTM: Button formula optimization

Good optimization to skip formula handling for Button type columns.

packages/nc-gui/composables/useInfiniteData.ts (1)

919-920: LGTM: AI prompt column handling

The addition of isAIPromptCol check ensures AI prompt columns are properly updated along with other special column types.

packages/nc-gui/components/workspace/integrations/forms/EditOrAddDatabase.vue (3)

661-662: LGTM: Improved button size

The button size change from xsmall to small improves visibility and clickability.


666-666: LGTM: More semantic icon choice

Changing the icon from "magic" to "link" better represents the connection URL functionality.


677-681: LGTM: Enhanced UX with auto-focus

Good addition of auto-focus for the textarea when the dropdown is opened, improving user experience.

packages/nocodb/src/db/formulav2/formulaQueryBuilderv2.ts (1)

5-5: LGTM: Import addition for AI text handling

The addition of LongTextAiMetaProp import is appropriate for the new AI text handling functionality.

packages/nc-gui/components/smartsheet/Kanban.vue (1)

1146-1146: Icon update for consistency

The icon change from 'expand' to 'maximize' aligns with similar updates in other components like Gallery.vue and attachment/index.vue.

packages/nc-gui/composables/useMultiSelect/index.ts (1)

6-6: LGTM: Type import for AI records

The addition of AIRecordType import provides proper typing for AI-related functionality.

Comment on lines +216 to +217
loadDynamicIntegrations()

Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider adding error handling for dynamic integrations loading

While the placement in onMounted is correct, consider adding error handling and loading state management for the async operation.

 onMounted(() => {
-  loadDynamicIntegrations()
+  try {
+    isLoading.value = true
+    await loadDynamicIntegrations()
+  } catch (error) {
+    console.error('Failed to load dynamic integrations:', error)
+    // Consider showing a user-friendly error message
+  } finally {
+    isLoading.value = false
+  }

   if (!integrationsCategoryFilter.value.length) {

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +114 to +119
<NcTooltip class="truncate" show-on-truncate-only :tooltip-style="{ zIndex: '10000' }">
<template #title>
{{ item?.title || '' }}
</template>
{{ item?.title || '' }}
</NcTooltip>
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Consider using a consistent z-index value

The hardcoded z-index value of 10000 in the tooltip is inconsistent with other tooltips in the codebase. Other tooltips use lower z-index values:

  • Other tooltips use z-index: 1049 (in ProjectNode.vue and ViewsNode.vue)
  • Most UI components use z-index values between 1-1000
  • Only InfiniteTable.vue uses similarly high values (100000, 100001)

Consider changing to:

-<NcTooltip class="truncate" show-on-truncate-only :tooltip-style="{ zIndex: '10000' }">
+<NcTooltip class="truncate" show-on-truncate-only :tooltip-style="{ zIndex: '1049' }">
🔗 Analysis chain

Review z-index value in tooltip

The hardcoded z-index value of 10000 could cause stacking context issues with other components.

Consider using a CSS variable for z-index management:

-<NcTooltip class="truncate" show-on-truncate-only :tooltip-style="{ zIndex: '10000' }">
+<NcTooltip class="truncate" show-on-truncate-only :tooltip-style="{ zIndex: 'var(--nc-tooltip-z-index, 1000)' }">
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other z-index values that might conflict
rg "z-index|zIndex" --type vue --type css

Length of output: 71


Script:

#!/bin/bash
# Search for z-index values in all files, focusing on Vue and CSS patterns
rg -i "z-index|zIndex" --type-add 'vue:*.vue' --type vue

Length of output: 4664

@@ -2139,13 +2137,13 @@ onKeyStroke('ArrowDown', onDown)
</span>
<div
v-else-if="!row.rowMeta.saving"
class="cursor-pointer flex items-center border-1 border-gray-100 active:ring rounded p-1 hover:(bg-gray-50)"
class="cursor-pointer flex items-center border-1 border-gray-100 active:ring rounded-md p-1 hover:(bg-white border-nc-border-gray-medium)"
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Check the validity of Tailwind CSS class syntax

The class attribute includes active:ring and hover:(bg-white border-nc-border-gray-medium), which may not be valid Tailwind CSS syntax. The active:ring class requires a ring width (e.g., active:ring-2), and the use of parentheses in hover:(...) may not be processed correctly. Update the class names to ensure proper styling.

Apply this diff to correct the class syntax:

-class="cursor-pointer flex items-center border-1 border-gray-100 active:ring rounded-md p-1 hover:(bg-white border-nc-border-gray-medium)"
+class="cursor-pointer flex items-center border border-gray-100 active:ring-2 rounded-md p-1 hover:bg-white hover:border-nc-border-gray-medium"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
class="cursor-pointer flex items-center border-1 border-gray-100 active:ring rounded-md p-1 hover:(bg-white border-nc-border-gray-medium)"
class="cursor-pointer flex items-center border border-gray-100 active:ring-2 rounded-md p-1 hover:bg-white hover:border-nc-border-gray-medium"

Comment on lines +198 to +201
if (integration.type === IntegrationsType.Ai) {
aiIntegrations.value = aiIntegrations.value.filter((i) => i.id !== integration.id)
}

Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Refactor repeated AI integration updates into a helper function

The code for updating aiIntegrations.value in deleteIntegration, updateIntegration, and setDefaultIntegration is similar. Consider refactoring this logic into a helper function to adhere to the DRY (Don't Repeat Yourself) principle and improve maintainability.

Here is a suggested refactor:

+// Helper function to update aiIntegrations based on integration action
+const updateAiIntegrations = (updateFn: (i: IntegrationType) => IntegrationType[]) => {
+  aiIntegrations.value = updateFn(aiIntegrations.value)
+}

Apply the helper function in your methods:

In deleteIntegration:

if (integration.type === IntegrationsType.Ai) {
-  aiIntegrations.value = aiIntegrations.value.filter((i) => i.id !== integration.id)
+  updateAiIntegrations((ais) => ais.filter((i) => i.id !== integration.id))
}

In updateIntegration:

if (integration.type === IntegrationsType.Ai) {
-  aiIntegrations.value = aiIntegrations.value.map((i) => {
-    if (i.id === integration.id) {
-      i.title = integration.title
-    }
-    return i
-  })
+  updateAiIntegrations((ais) =>
+    ais.map((i) =>
+      i.id === integration.id ? { ...i, title: integration.title } : i
+    )
+  )
}

In setDefaultIntegration:

if (integration.type === IntegrationsType.Ai) {
-  aiIntegrations.value = aiIntegrations.value.map((i) => {
-    if (i.id === integration.id) {
-      i.is_default = true
-    } else {
-      i.is_default = false
-    }
-    return i
-  })
+  updateAiIntegrations((ais) =>
+    ais.map((i) => ({
+      ...i,
+      is_default: i.id === integration.id,
+    }))
+  )
}

This refactoring reduces code duplication and centralizes the update logic for AI integrations.

Also applies to: 229-238, 258-269

<div class="text-sm text-gray-800 select-none">
{{ $t('labels.enableRichText') }}
<NcTooltip :disabled="!isEnabledGenerateText">
<template #title> Rich text formatting is not supported when generate text using AI is enabled </template>
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Localize user-facing strings for internationalization support

Several user-facing strings are hardcoded and not wrapped with the localization function. Wrapping these strings ensures they can be translated for international users.

Update the strings as follows:

-<template #title> Rich text formatting is not supported when generate text using AI is enabled </template>
+<template #title>{{ t('messages.richTextNotSupportedWithAI') }}</template>

-<template #title> Generate text using AI is not supported when rich text formatting is enabled </template>
+<template #title>{{ t('messages.aiNotSupportedWithRichText') }}</template>

-<template #title> Use AI to generate content based on record data. </template>
+<template #title>{{ t('messages.useAIToGenerateContent') }}</template>

-placeholder="Write custom AI Prompt instruction here"
+:placeholder="t('placeholders.writeCustomAIPrompt')"

-<span class="text-xs text-nc-content-gray-subtle2">
-  Mention fields using curly braces, e.g. <span class="text-nc-content-purple-dark">{Field name}</span>.
-</span>
+<span class="text-xs text-nc-content-gray-subtle2" v-html="t('messages.mentionFieldsUsingCurlyBraces')"></span>

-<template #title> Preview is generated using the first record in this table</template>
+<template #title>{{ t('messages.previewGeneratedUsingFirstRecord') }}</template>

-<template #title> Include at least 1 field in prompt to generate </template>
+<template #title>{{ t('messages.includeFieldInPromptToGenerate') }}</template>

Note: Ensure that the corresponding translation keys are added to your localization files.

Also applies to: 187-187, 207-207, 243-243, 261-261, 274-274

Comment on lines +8636 to +8654
if (d) {
for (const col of jsonColumns) {
if (d[col.id] && typeof d[col.id] === 'string') {
try {
d[col.id] = JSON.parse(d[col.id]);
}
} catch {}
}

if (d[col.id]?.length) {
for (let i = 0; i < d[col.id].length; i++) {
if (typeof d[col.id][i] === 'string') {
if (d[col.id]?.length) {
for (let i = 0; i < d[col.id].length; i++) {
if (typeof d[col.id][i] === 'string') {
try {
d[col.id][i] = JSON.parse(d[col.id][i]);
}
} catch {}
}
}
}
}
} catch {}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

Avoid Swallowing Exceptions in _convertJsonType

In the _convertJsonType method, the catch block after JSON.parse is empty. Swallowing exceptions can make debugging difficult. Consider logging the error or handling it appropriately.

Apply this diff to handle parsing errors:

          try {
            d[col.id] = JSON.parse(d[col.id]);
-         } catch {}
+         } catch (e) {
+           console.error(`Error parsing JSON for column ${col.id}:`, e);
+           // Optionally rethrow or handle the error as needed
+         }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +6 to +22
table.string('id', 20).primary();
table.string('fk_workspace_id', 20);
table.string('base_id', 20);
table.string('fk_model_id', 20);
table.string('fk_column_id', 20);

table.string('fk_integration_id', 20);
table.string('model', 255);

table.text('prompt');
table.text('prompt_raw');
table.text('error');

table.timestamps(true, true);

table.index('fk_column_id');
});
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Define Foreign Key Constraints for Referenced IDs

When creating the MetaTable.COL_LONG_TEXT table, consider adding foreign key constraints to columns like fk_workspace_id, base_id, fk_model_id, and fk_column_id to ensure referential integrity within the database.

Example:

        table.string('fk_workspace_id', 20)
+         .references('id')
+         .inTable('nc_workspace')
+         .onDelete('CASCADE');

Apply similar constraints to other foreign key columns.

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +43 to +44
export const isAI = (column: ColumnType) =>
column.uidt === UITypes.LongText && parseProp(column?.meta)?.[LongTextAiMetaProp] === true
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add missing import and handle potential undefined access.

The implementation has two issues:

  1. LongTextAiMetaProp is not imported
  2. column?.meta could be undefined before parsing

Apply this fix:

+ import { LongTextAiMetaProp } from './globals'
- export const isAI = (column: ColumnType) =>
-   column.uidt === UITypes.LongText && parseProp(column?.meta)?.[LongTextAiMetaProp] === true
+ export const isAI = (column: ColumnType) => {
+   if (!column || column.uidt !== UITypes.LongText) return false
+   const meta = parseProp(column.meta)
+   return meta?.[LongTextAiMetaProp] === true
+ }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const isAI = (column: ColumnType) =>
column.uidt === UITypes.LongText && parseProp(column?.meta)?.[LongTextAiMetaProp] === true
import { LongTextAiMetaProp } from './globals'
export const isAI = (column: ColumnType) => {
if (!column || column.uidt !== UITypes.LongText) return false
const meta = parseProp(column.meta)
return meta?.[LongTextAiMetaProp] === true
}

Comment on lines +191 to +197
export function isAIPromptCol(
col:
| ColumnReqType
| ColumnType
) {
return col.uidt === UITypes.LongText && parseHelper((col as any)?.meta)?.[LongTextAiMetaProp];
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve type safety in isAIPromptCol function

The function uses type casting with (col as any)?.meta which bypasses TypeScript's type checking. Consider improving type safety:

-export function isAIPromptCol(
-  col:
-    | ColumnReqType
-    | ColumnType
-) {
-  return col.uidt === UITypes.LongText && parseHelper((col as any)?.meta)?.[LongTextAiMetaProp];
-}
+export function isAIPromptCol(
+  col: ColumnReqType | ColumnType & { meta?: Record<string, unknown> }
+) {
+  return col.uidt === UITypes.LongText && parseHelper(col.meta)?.[LongTextAiMetaProp];
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function isAIPromptCol(
col:
| ColumnReqType
| ColumnType
) {
return col.uidt === UITypes.LongText && parseHelper((col as any)?.meta)?.[LongTextAiMetaProp];
}
export function isAIPromptCol(
col: ColumnReqType | ColumnType & { meta?: Record<string, unknown> }
) {
return col.uidt === UITypes.LongText && parseHelper(col.meta)?.[LongTextAiMetaProp];
}

Comment on lines +474 to +500
// unbind all buttons and long texts associated with this integration
await ncMeta.metaUpdate(
this.fk_workspace_id ? this.fk_workspace_id : RootScopes.WORKSPACE,
RootScopes.WORKSPACE,
MetaTable.COL_BUTTON,
{
fk_integration_id: null,
model: null,
},
{
fk_integration_id: this.id,
},
);

await ncMeta.metaUpdate(
this.fk_workspace_id ? this.fk_workspace_id : RootScopes.WORKSPACE,
RootScopes.WORKSPACE,
MetaTable.COL_LONG_TEXT,
{
fk_integration_id: null,
model: null,
},
{
fk_integration_id: this.id,
},
);

Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider extracting duplicated unbinding logic

The unbinding logic for buttons and long texts is identical in both delete() and softDelete() methods. Consider extracting this into a private method to improve maintainability and reduce code duplication.

+  private async unbindButtonsAndLongTexts(ncMeta = Noco.ncMeta) {
+    await ncMeta.metaUpdate(
+      this.fk_workspace_id ? this.fk_workspace_id : RootScopes.WORKSPACE,
+      RootScopes.WORKSPACE,
+      MetaTable.COL_BUTTON,
+      {
+        fk_integration_id: null,
+        model: null,
+      },
+      {
+        fk_integration_id: this.id,
+      },
+    );
+
+    await ncMeta.metaUpdate(
+      this.fk_workspace_id ? this.fk_workspace_id : RootScopes.WORKSPACE,
+      RootScopes.WORKSPACE,
+      MetaTable.COL_LONG_TEXT,
+      {
+        fk_integration_id: null,
+        model: null,
+      },
+      {
+        fk_integration_id: this.id,
+      },
+    );
+  }

   async delete(ncMeta = Noco.ncMeta) {
     const sources = await this.getSources(ncMeta, true);
     for (const source of sources) {
       await source.delete(
         {
           workspace_id: this.fk_workspace_id,
           base_id: source.base_id,
         },
         ncMeta,
       );
     }
-    await ncMeta.metaUpdate(/*...*/);
-    await ncMeta.metaUpdate(/*...*/);
+    await this.unbindButtonsAndLongTexts(ncMeta);
     return await ncMeta.metaDelete(/*...*/);
   }

   async softDelete(ncMeta = Noco.ncMeta) {
     const sources = await this.getSources(ncMeta, true);
     for (const source of sources) {
       await source.softDelete(/*...*/);
     }
-    await ncMeta.metaUpdate(/*...*/);
-    await ncMeta.metaUpdate(/*...*/);
+    await this.unbindButtonsAndLongTexts(ncMeta);
     await ncMeta.metaUpdate(/*...*/);
   }

Also applies to: 522-548

@dosubot dosubot bot added the lgtm This PR has been approved by a maintainer label Dec 7, 2024
Signed-off-by: mertmit <mertmit99@gmail.com>
Signed-off-by: mertmit <mertmit99@gmail.com>
Copy link
Contributor
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Outside diff range and nitpick comments (21)
packages/nc-gui/components/workspace/integrations/forms/EditOrAddDatabase.vue (1)

675-681: Consider using Vue's autofocus directive for better maintainability.

While the current implementation works, using Vue's built-in autofocus directive would be more idiomatic and maintainable.

Consider this alternative implementation:

-          <a-textarea
-            :ref="
-              (el) => {
-                el?.$el?.focus()
-              }
-            }"
-            v-model:value="importURL"
-            class="!rounded-lg !min-h-[120px] !max-h-[250px] nc-scrollbar-thin"
-          ></a-textarea>
+          <a-textarea
+            autofocus
+            v-model:value="importURL"
+            class="!rounded-lg !min-h-[120px] !max-h-[250px] nc-scrollbar-thin"
+          ></a-textarea>
packages/nc-gui/components/smartsheet/column/AiButtonOptions.vue (2)

471-475: Consider adding aria-label for better accessibility

While the tooltip implementation is good for UX, consider enhancing accessibility by adding an aria-label to the truncated text container.

 <NcTooltip show-on-truncate-only class="truncate max-w-[150px]">
   <template #title>{{ op.title }}</template>
-   {{ op.title }}
+   <span :aria-label="op.title">{{ op.title }}</span>
 </NcTooltip>

687-688: Consider refactoring repeated conditional styling logic

The checklist indicator styling contains repeated conditional logic. Consider extracting this into a computed property or method to reduce duplication and improve maintainability.

+ const getIndicatorClass = (condition: boolean) => ({
+   'bg-nc-bg-green-dark text-nc-content-green-dark': condition,
+   'bg-nc-bg-red-dark text-nc-content-red-dark': !condition
+ })

- :class="
-   inputColumns.length
-     ? 'bg-nc-bg-green-dark text-nc-content-green-dark'
-     : 'bg-nc-bg-red-dark text-nc-content-red-dark'
- "
+ :class="getIndicatorClass(inputColumns.length)"

- :class="
-   outputColumnIds.length
-     ? 'bg-nc-bg-green-dark text-nc-content-green-dark'
-     : 'bg-nc-bg-red-dark text-nc-content-red-dark'
- "
+ :class="getIndicatorClass(outputColumnIds.length)"

- :class="
-   selectedRecordPk
-     ? 'bg-nc-bg-green-dark text-nc-content-green-dark'
-     : 'bg-nc-bg-red-dark text-nc-content-red-dark'
- "
+ :class="getIndicatorClass(!!selectedRecordPk)"

Also applies to: 698-702, 711-715, 724-728

packages/nc-gui/components/cell/TextArea.vue (2)

531-547: Enhance accessibility for the re-generate button

While the button implementation is functional, it could benefit from improved accessibility.

Apply this diff to enhance accessibility:

 <NcButton
   type="secondary"
   size="xsmall"
   class="!p-0 !w-5 !h-5 !min-w-[fit-content]"
   :disabled="isAiGenerating"
   loader-size="small"
   icon-only
+  :aria-label="isAiGenerating ? 'Re-generating content' : 'Re-generate content'"
+  :aria-busy="isAiGenerating"
   @click.stop="generate"
 >

726-726: Consider reducing CSS specificity and avoiding !important

The use of !important declarations and high specificity selectors can make styles harder to maintain and override when needed.

Consider refactoring the styles to use more specific selectors or CSS custom properties instead of !important:

- @apply !flex cursor-pointer;
+ @apply flex cursor-pointer;

- &:has(.nc-cell-longtext-ai .nc-expanded-form-open) {
-   @apply !border-none -mx-1 -my-1;
-   box-shadow: none !important;
+ .nc-cell-longtext-ai-expanded {
+   @apply border-none -mx-1 -my-1;
+   box-shadow: none;

Also applies to: 742-752

packages/nc-gui/composables/useIntegrationsStore.ts (3)

301-309: Enhance type safety when creating AI integration

Consider using type-safe object creation for consistency and maintainability.

 if (response.type === IntegrationsType.Ai) {
+  const { id, title, is_default, type, sub_type } = response
   aiIntegrations.value.push({
-    id: response.id,
-    title: response.title,
-    is_default: response.is_default,
-    type: response.type,
-    sub_type: response.sub_type,
+    id,
+    title,
+    is_default,
+    type,
+    sub_type,
   })
 }

Line range hint 447-496: Separate icon handling logic from integration loading

The function handles both integration loading and icon processing, which violates the Single Responsibility Principle.

Consider extracting the icon handling logic:

+const resolveIntegrationIcon = (iconMeta: string | undefined) => {
+  if (!iconMeta) return iconMap.puzzle
+  
+  if (iconMeta in iconMap) {
+    return iconMap[iconMeta as keyof typeof iconMap]
+  }
+  
+  if (isValidURL(iconMeta)) {
+    return h('img', {
+      src: iconMeta,
+      alt: iconMeta
+    })
+  }
+  
+  return iconMap.puzzle
+}

 const loadDynamicIntegrations = async () => {
   if (integrationsInitialized.value) return
   
   try {
     integrationsInitialized.value = true
     
     const dynamicIntegrations = await $api.integrations.list()
     
     dynamicIntegrations
       .sort((a, b) => (a.meta.order ?? Infinity) - (b.meta.order ?? Infinity))
       .forEach(di => {
         allIntegrations.push({
           title: di.meta.title || di.subType,
           subType: di.subType,
           icon: resolveIntegrationIcon(di.meta.icon),
           type: di.type,
           isAvailable: true,
           dynamic: true,
         })
       })
     
     integrationsRefreshKey.value++
   } catch (error) {
     console.error('Failed to load dynamic integrations:', error)
     throw error
   }
 }

296-296: Use optional chaining for safer property access

Replace the conditional check with optional chaining for better readability and safety.

-if (response && response?.id) {
+if (response?.id) {
🧰 Tools
🪛 Biome (1.9.4)

[error] 296-296: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

packages/nc-gui/composables/useNocoAi.ts (1)

22-23: Consider using Boolean() for explicit type conversion

While the double negation (!!) works correctly, using Boolean() would make the intention more explicit:

-const aiIntegrationAvailable = computed(() => !!aiIntegrations.value.length)
+const aiIntegrationAvailable = computed(() => Boolean(aiIntegrations.value.length))
packages/nocodb/src/models/AIColumn.ts (2)

26-26: Replace 'this' with class name in static method

Using this in static methods can be confusing. Replace this with the class name AIColumn for clarity.

Apply this diff:

-        return this._insert(
+        return AIColumn._insert(
          context,
          aiColumn,
          ['fk_integration_id', 'model', 'prompt', 'prompt_raw', 'error'],
          ncMeta,
        );
🧰 Tools
🪛 Biome (1.9.4)

[error] 26-26: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


40-40: Replace 'this' with class name in static method

Similarly, replace this with AIColumn in the static method for better clarity.

Apply this diff:

-        return this._update(
+        return AIColumn._update(
          context,
          columnId,
          aiColumn,
          ['fk_integration_id', 'model', 'prompt', 'prompt_raw', 'error'],
          ncMeta,
        );
🧰 Tools
🪛 Biome (1.9.4)

[error] 40-40: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

packages/nocodb-sdk/src/lib/helperFunctions.ts (1)

239-244: Ensure stringifyHelper consistently returns a string

The stringifyHelper function may return a non-string value if JSON.stringify fails. Modify it to always return a string to match its return type.

Apply this diff:

 export function stringifyHelper(v: any): string {
   try {
     return JSON.stringify(v);
   } catch {
-    return v;
+    return String(v);
   }
 }

This ensures that the function always returns a string, even if serialization fails.

packages/nc-gui/components/ai/PromptWithFields.vue (2)

44-45: Consider using computed property for editor configuration

The readOnly ref is destructured but could be more efficiently used in a computed property for the editor configuration.

-const { autoFocus, readOnly } = toRefs(props)
+const editorConfig = computed(() => ({
+  content: vModel.value,
+  editable: !props.readOnly,
+  autofocus: props.autoFocus,
+  // ... rest of the config
+}))

194-211: Enhance button accessibility

The button's disabled state should include ARIA attributes for better screen reader support.

 <NcButton
   size="xs"
   type="text"
   class="nc-prompt-with-field-suggestion-btn !px-1"
   :disabled="readOnly"
+  :aria-disabled="readOnly"
+  :aria-label="readOnly ? 'Field suggestion disabled' : 'Add field suggestion'"
   @click.stop="newFieldSuggestionNode"
 >
packages/nc-gui/components/ai/Settings.vue (1)

Line range hint 36-86: Prevent race conditions in model loading

The model loading logic could result in race conditions when multiple integration changes occur rapidly. Consider implementing request cancellation.

+const currentRequest = ref<AbortController | null>(null)

 const  (newFkINtegrationId?: string) => {
   if (!vFkIntegrationId.value && !newFkINtegrationId) return
+  
+  // Cancel any ongoing request
+  if (currentRequest.value) {
+    currentRequest.value.abort()
+  }
+  currentRequest.value = new AbortController()

   if (!newFkINtegrationId) {
     newFkINtegrationId = vFkIntegrationId.value
   }

   availableModels.value = []

   if (lastIntegrationId.value !== newFkINtegrationId) {
     vModel.value = undefined
   }

   isLoadingAvailableModels.value = true

   try {
-    const response = await $api.integrations.endpoint(newFkINtegrationId, 'availableModels', {})
+    const response = await $api.integrations.endpoint(
+      newFkINtegrationId,
+      'availableModels',
+      {},
+      { signal: currentRequest.value.signal }
+    )
     availableModels.value = (response || []) as { value: string; label: string }[]

     if (!vModel.value && availableModels.value.length > 0) {
       vModel.value = availableModels.value[0].value
     }
   } catch (error) {
+    if (error.name === 'AbortError') return
     console.error(error)
   } finally {
     isLoadingAvailableModels.value = false
+    currentRequest.value = null
   }
 }
packages/nc-gui/utils/columnUtils.ts (1)

15-17: Consider using an enum for AI-related constants

The AI-related constants could be better organized using an enum for type safety and maintainability.

-export const AIButton = 'AIButton'
-export const AIPrompt = 'AIPrompt'

+export enum AITypes {
+  Button = 'AIButton',
+  Prompt = 'AIPrompt'
+}
packages/nc-gui/components/smartsheet/Cell.vue (1)

150-176: Excellent refactoring of cell type determination logic!

The new cellType computed property effectively consolidates multiple type-checking functions into a single, maintainable property. This improves code readability and reduces the complexity of the template logic.

Consider adding JSDoc comments to document the return type and possible values:

+/**
+ * Determines the type of cell based on column properties
+ * @returns {'ai'|'textarea'|'geoData'|'checkbox'|'attachment'|'singleSelect'|'multiSelect'|
+ *          'datePicker'|'yearPicker'|'dateTimePicker'|'timePicker'|'rating'|'duration'|
+ *          'email'|'url'|'phoneNumber'|'percent'|'currency'|'user'|'decimal'|'float'|
+ *          'text'|'integer'|'json'}
+ */
const cellType = computed(() => {
packages/nc-gui/components/workspace/project/AiCreateProject.vue (1)

150-164: Well-structured prompt enhancement with optional details

The prompt construction logic effectively incorporates optional organization, industry, and audience details while maintaining clean code structure. The event tracking addition is also appropriate.

Consider extracting the prompt construction logic into a separate function for better reusability:

+const constructPrompt = (formState) => {
+  let prompt = formState.prompt
+  
+  const optionalFields = {
+    organization: 'Organization',
+    industry: 'Industry',
+    audience: 'Audience'
+  }
+  
+  Object.entries(optionalFields).forEach(([key, label]) => {
+    if (formState[key]?.trim()) {
+      prompt += ` | ${label}: ${formState[key]}`
+    }
+  })
+  
+  return prompt
+}

-let prompt = `${aiFormState.value.prompt}`
-if (aiFormState.value.organization?.trim()) {
-  prompt += ` | Organization: ${aiFormState.value.organization}`
-}
-if (aiFormState.value.industry?.trim()) {
-  prompt += ` | Industry: ${aiFormState.value.industry}`
-}
-if (aiFormState.value.audience?.trim()) {
-  prompt += ` | Audience: ${aiFormState.value.audience}`
-}
+const prompt = constructPrompt(aiFormState.value)
packages/nc-gui/components/smartsheet/header/Menu.vue (1)

Line range hint 330-334: Consider using a constant for delay duration

The hardcoded delay of 5000ms should be extracted into a constant for better maintainability.

+const COPY_FEEDBACK_DELAY = 5000;
+
 const  (field: ColumnType) => {
   await copy(field.id!)
   isFieldIdCopied.value = true
-  await ncDelay(5000)
+  await ncDelay(COPY_FEEDBACK_DELAY)
   isFieldIdCopied.value = false
 }
packages/nc-gui/components/smartsheet/expanded-form/index.vue (1)

330-333: Maintain consistency with Menu.vue copy feedback

This implementation mirrors the copy feedback in Menu.vue. Consider extracting the delay duration to a shared constant.

+import { COPY_FEEDBACK_DELAY } from '../constants';
+
 const copyRecordUrl = async () => {
   await copy(encodeURI(`${dashboardUrl?.value}#/${route.params.typeOrId}/${route.params.baseId}/${meta.value?.id}${props.view ? `/${props.view.title}` : ''}?rowId=${primaryKey.value}`))
   isRecordLinkCopied.value = true
-  await ncDelay(5000)
+  await ncDelay(COPY_FEEDBACK_DELAY)
   isRecordLinkCopied.value = false
 }
packages/nc-gui/components/smartsheet/column/EditOrAdd.vue (1)

1102-1108: Consider extracting icon selection logic to a computed property

The nested ternary operator makes the template logic harder to read and maintain.

Consider refactoring to a computed property:

+ computed: {
+   getColumnTypeIcon() {
+     if (this.isAiButtonSelectOption(this.opt.name) && !this.isColumnTypeOpen) {
+       return this.iconMap.cellAiButton;
+     }
+     if (this.isAiPromptSelectOption(this.opt.name) && !this.isColumnTypeOpen) {
+       return this.iconMap.cellAi;
+     }
+     return this.opt.icon;
+   }
+ }

- :is="isAiButtonSelectOption(opt.name) && !isColumnTypeOpen
-   ? iconMap.cellAiButton
-   : isAiPromptSelectOption(opt.name) && !isColumnTypeOpen
-   ? iconMap.cellAi
-   : opt.icon"
+ :is="getColumnTypeIcon"
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 58a8a11 and e20ae7d.

📒 Files selected for processing (72)
  • packages/nc-gui/components/ai/PromptWithFields.vue (8 hunks)
  • packages/nc-gui/components/ai/Settings.vue (9 hunks)
  • packages/nc-gui/components/cell/AI.vue (8 hunks)
  • packages/nc-gui/components/cell/TextArea.vue (11 hunks)
  • packages/nc-gui/components/cell/attachment/index.vue (1 hunks)
  • packages/nc-gui/components/general/IntegrationIcon.vue (1 hunks)
  • packages/nc-gui/components/general/Loader.vue (1 hunks)
  • packages/nc-gui/components/nc/Button.vue (6 hunks)
  • packages/nc-gui/components/nc/List/RecordItem.vue (1 hunks)
  • packages/nc-gui/components/nc/Switch.vue (2 hunks)
  • packages/nc-gui/components/smartsheet/Cell.vue (3 hunks)
  • packages/nc-gui/components/smartsheet/Gallery.vue (1 hunks)
  • packages/nc-gui/components/smartsheet/Kanban.vue (1 hunks)
  • packages/nc-gui/components/smartsheet/PlainCell.vue (2 hunks)
  • packages/nc-gui/components/smartsheet/column/AiButtonOptions.vue (6 hunks)
  • packages/nc-gui/components/smartsheet/column/ButtonOptions.vue (2 hunks)
  • packages/nc-gui/components/smartsheet/column/EditOrAdd.vue (7 hunks)
  • packages/nc-gui/components/smartsheet/column/LongTextOptions.vue (4 hunks)
  • packages/nc-gui/components/smartsheet/column/UITypesOptionsWithSearch.vue (2 hunks)
  • packages/nc-gui/components/smartsheet/details/Fields.vue (1 hunks)
  • packages/nc-gui/components/smartsheet/expanded-form/index.vue (1 hunks)
  • packages/nc-gui/components/smartsheet/grid/GroupByTable.vue (1 hunks)
  • packages/nc-gui/components/smartsheet/grid/InfiniteTable.vue (4 hunks)
  • packages/nc-gui/components/smartsheet/grid/Table.vue (4 hunks)
  • packages/nc-gui/components/smartsheet/header/Cell.vue (1 hunks)
  • packages/nc-gui/components/smartsheet/header/CellIcon.ts (1 hunks)
  • packages/nc-gui/components/smartsheet/header/Menu.vue (4 hunks)
  • packages/nc-gui/components/smartsheet/header/VirtualCell.vue (1 hunks)
  • packages/nc-gui/components/smartsheet/toolbar/ViewActionMenu.vue (1 hunks)
  • packages/nc-gui/components/virtual-cell/Button.vue (1 hunks)
  • packages/nc-gui/components/virtual-cell/HasMany.vue (1 hunks)
  • packages/nc-gui/components/virtual-cell/ManyToMany.vue (1 hunks)
  • packages/nc-gui/components/virtual-cell/components/ListItem.vue (1 hunks)
  • packages/nc-gui/components/workspace/integrations/ConnectionsTab.vue (0 hunks)
  • packages/nc-gui/components/workspace/integrations/IntegrationsTab.vue (2 hunks)
  • packages/nc-gui/components/workspace/integrations/forms/EditOrAddCommon.vue (1 hunks)
  • packages/nc-gui/components/workspace/integrations/forms/EditOrAddDatabase.vue (2 hunks)
  • packages/nc-gui/components/workspace/project/AiCreateProject.vue (2 hunks)
  • packages/nc-gui/composables/useColumnCreateStore.ts (2 hunks)
  • packages/nc-gui/composables/useData.ts (2 hunks)
  • packages/nc-gui/composables/useInfiniteData.ts (2 hunks)
  • packages/nc-gui/composables/useIntegrationsStore.ts (8 hunks)
  • packages/nc-gui/composables/useMultiSelect/index.ts (2 hunks)
  • packages/nc-gui/composables/useNocoAi.ts (3 hunks)
  • packages/nc-gui/helpers/parsers/parserHelpers.ts (2 hunks)
  • packages/nc-gui/helpers/tiptapExtensions/mention/FieldList.vue (3 hunks)
  • packages/nc-gui/nuxt.config.ts (3 hunks)
  • packages/nc-gui/utils/cell.ts (1 hunks)
  • packages/nc-gui/utils/columnUtils.ts (4 hunks)
  • packages/nc-gui/utils/commonUtils.ts (1 hunks)
  • packages/nocodb-sdk/src/lib/Api.ts (0 hunks)
  • packages/nocodb-sdk/src/lib/UITypes.ts (3 hunks)
  • packages/nocodb-sdk/src/lib/globals.ts (1 hunks)
  • packages/nocodb-sdk/src/lib/helperFunctions.ts (1 hunks)
  • packages/nocodb-sdk/src/lib/index.ts (1 hunks)
  • packages/nocodb/src/db/BaseModelSqlv2.ts (8 hunks)
  • packages/nocodb/src/db/conditionV2.ts (2 hunks)
  • packages/nocodb/src/db/formulav2/formulaQueryBuilderv2.ts (2 hunks)
  • packages/nocodb/src/db/sortV2.ts (2 hunks)
  • packages/nocodb/src/meta/migrations/XcMigrationSourcev2.ts (3 hunks)
  • packages/nocodb/src/meta/migrations/v2/nc_069_ai_prompt.ts (1 hunks)
  • packages/nocodb/src/models/AIColumn.ts (1 hunks)
  • packages/nocodb/src/models/Column.ts (9 hunks)
  • packages/nocodb/src/models/Integration.ts (3 hunks)
  • packages/nocodb/src/models/LongTextColumn.ts (1 hunks)
  • packages/nocodb/src/models/index.ts (1 hunks)
  • packages/nocodb/src/modules/jobs/jobs/export-import/duplicate.processor.ts (2 hunks)
  • packages/nocodb/src/modules/jobs/jobs/export-import/export.service.ts (4 hunks)
  • packages/nocodb/src/modules/jobs/jobs/export-import/import.service.ts (5 hunks)
  • packages/nocodb/src/services/columns.service.ts (4 hunks)
  • packages/nocodb/src/utils/dataConversion.ts (1 hunks)
  • packages/nocodb/src/utils/globals.ts (3 hunks)
💤 Files with no reviewable changes (2)
  • packages/nc-gui/components/workspace/integrations/ConnectionsTab.vue
  • packages/nocodb-sdk/src/lib/Api.ts
🚧 Files skipped from review as they are similar to previous changes (43)
  • packages/nc-gui/components/smartsheet/header/CellIcon.ts
  • packages/nocodb/src/meta/migrations/v2/nc_069_ai_prompt.ts
  • packages/nc-gui/components/virtual-cell/HasMany.vue
  • packages/nocodb/src/utils/globals.ts
  • packages/nc-gui/components/smartsheet/column/UITypesOptionsWithSearch.vue
  • packages/nocodb-sdk/src/lib/UITypes.ts
  • packages/nocodb/src/models/index.ts
  • packages/nc-gui/nuxt.config.ts
  • packages/nc-gui/components/nc/Switch.vue
  • packages/nc-gui/composables/useInfiniteData.ts
  • packages/nc-gui/components/nc/List/RecordItem.vue
  • packages/nc-gui/utils/commonUtils.ts
  • packages/nc-gui/components/nc/Button.vue
  • packages/nocodb-sdk/src/lib/index.ts
  • packages/nocodb/src/modules/jobs/jobs/export-import/duplicate.processor.ts
  • packages/nc-gui/components/virtual-cell/Button.vue
  • packages/nc-gui/components/workspace/integrations/IntegrationsTab.vue
  • packages/nc-gui/utils/cell.ts
  • packages/nc-gui/components/workspace/integrations/forms/EditOrAddCommon.vue
  • packages/nc-gui/components/smartsheet/Gallery.vue
  • packages/nc-gui/composables/useData.ts
  • packages/nocodb-sdk/src/lib/globals.ts
  • packages/nc-gui/components/smartsheet/PlainCell.vue
  • packages/nc-gui/composables/useColumnCreateStore.ts
  • packages/nc-gui/components/virtual-cell/ManyToMany.vue
  • packages/nc-gui/components/smartsheet/header/VirtualCell.vue
  • packages/nc-gui/components/cell/attachment/index.vue
  • packages/nc-gui/composables/useMultiSelect/index.ts
  • packages/nocodb/src/db/sortV2.ts
  • packages/nc-gui/components/smartsheet/toolbar/ViewActionMenu.vue
  • packages/nc-gui/components/smartsheet/header/Cell.vue
  • packages/nc-gui/components/smartsheet/Kanban.vue
  • packages/nc-gui/helpers/tiptapExtensions/mention/FieldList.vue
  • packages/nc-gui/helpers/parsers/parserHelpers.ts
  • packages/nc-gui/components/virtual-cell/components/ListItem.vue
  • packages/nocodb/src/meta/migrations/XcMigrationSourcev2.ts
  • packages/nc-gui/components/general/Loader.vue
  • packages/nc-gui/components/smartsheet/grid/GroupByTable.vue
  • packages/nc-gui/components/general/IntegrationIcon.vue
  • packages/nc-gui/components/smartsheet/column/ButtonOptions.vue
  • packages/nc-gui/components/cell/AI.vue
  • packages/nocodb/src/modules/jobs/jobs/export-import/export.service.ts
  • packages/nocodb/src/models/Integration.ts
🧰 Additional context used
🪛 Biome (1.9.4)
packages/nc-gui/composables/useIntegrationsStore.ts

[error] 296-296: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

packages/nocodb/src/models/Column.ts

[error] 921-921: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

packages/nocodb/src/models/AIColumn.ts

[error] 26-26: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 40-40: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

packages/nocodb/src/models/LongTextColumn.ts

[error] 61-61: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 85-85: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

🔇 Additional comments (43)
packages/nc-gui/components/workspace/integrations/forms/EditOrAddDatabase.vue (1)

661-662: LGTM! UI improvements enhance usability.

The changes improve the user interface by:

  • Using a more semantically appropriate 'link' icon for the URL input feature
  • Increasing button size for better accessibility

Also applies to: 666-666

packages/nc-gui/components/smartsheet/column/AiButtonOptions.vue (1)

369-369: LGTM: Clean prop addition for edit mode support

The addition of is-edit-column prop follows Vue conventions and provides clear control over edit mode behavior.

packages/nc-gui/components/smartsheet/grid/InfiniteTable.vue (3)

1051-1051: LGTM!

The addition of isAiButton check enhances the AI functionality by properly handling AI button fields.


1027-1028: ⚠️ Potential issue

Missing import for isAiButton function

The isAiButton function is used but not imported, which will cause a runtime error.

Add the missing import:

 import {
   type ButtonType,
   type ColumnReqType,
   type ColumnType,
   type TableType,
   UITypes,
   type ViewType,
   ViewTypes,
   isAIPromptCol,
+  isAiButton,
   isCreatedOrLastModifiedByCol,
   isCreatedOrLastModifiedTimeCol,
   isLinksOrLTAR,
   isSystemColumn,
   isVirtualCol,
 } from 'nocodb-sdk'

2249-2252: ⚠️ Potential issue

Undefined iconMap variable

The template uses iconMap but it's not imported or defined, which will cause a runtime error.

Add the following code to fix this issue:

 const { $e } = useNuxtApp()
+const { iconMap } = useNocoIcons()
 const { api } = useApi()

Also ensure that useNocoIcons is imported:

 import { useNuxtApp } from '#imports'
+import { useNocoIcons } from '#imports'
packages/nc-gui/components/smartsheet/grid/Table.vue (4)

Line range hint 879-885: LGTM! Well-structured condition check

The condition properly validates the field type and safely handles the output column IDs parsing.


2143-2146: LGTM! Well-structured icon component

The changes properly implement:

  • Dynamic component binding for the expand icon
  • Event tracking for analytics
  • Proper use of Vue directives

855-856: ⚠️ Potential issue

Define or import the isAiButton function

The isAiButton(field) function is used but not defined or imported in the code. This will cause a ReferenceError at runtime.


2140-2140: ⚠️ Potential issue

Fix invalid Tailwind CSS class syntax

The class hover:(bg-white border-nc-border-gray-medium) uses invalid syntax. Split it into individual hover classes.

-class="cursor-pointer flex items-center border-1 border-gray-100 active:ring rounded-md p-1 hover:(bg-white border-nc-border-gray-medium)"
+class="cursor-pointer flex items-center border border-gray-100 active:ring-2 rounded-md p-1 hover:bg-white hover:border-nc-border-gray-medium"
packages/nc-gui/components/cell/TextArea.vue (1)

100-102: ⚠️ Potential issue

Add null checks to prevent potential runtime errors

The use of non-null assertions (!) in meta.value!.columns! can lead to runtime errors if either meta.value or meta.value.columns is null or undefined.

Apply this diff to add proper null checks:

 const rowId = computed(() => {
-  return extractPkFromRow(currentRow.value?.row, meta.value!.columns!)
+  if (!meta.value?.columns) {
+    return null
+  }
+  return extractPkFromRow(currentRow.value?.row, meta.value.columns)
 })

Likely invalid or redundant comment.

packages/nc-gui/composables/useIntegrationsStore.ts (5)

93-94: LGTM: Clean integration of AI state management

The addition of aiIntegrations from useNocoAi composable follows Vue.js best practices for state management.


541-541: LGTM: Clean export addition

The addition of loadDynamicIntegrations to store exports is clean and follows the existing pattern.


191-201: 🛠️ Refactor suggestion

Refactor repeated AI integration updates into a helper function

The AI integration state update logic is duplicated across multiple functions (delete, update, setDefault).

As suggested in the previous review, consider extracting this logic into a helper function:

+const updateAiIntegrations = (updateFn: (integrations: IntegrationType[]) => IntegrationType[]) => {
+  aiIntegrations.value = updateFn(aiIntegrations.value)
+}

 const deleteIntegration = async (integration: IntegrationType, force = false) => {
   // ...
   if (integration.type === IntegrationsType.Ai) {
-    aiIntegrations.value = aiIntegrations.value.filter((i) => i.id !== integration.id)
+    updateAiIntegrations(ais => ais.filter(i => i.id !== integration.id))
   }
   // ...
 }

258-269: 🛠️ Refactor suggestion

Simplify default integration logic with immutable updates

The current implementation is verbose and mutates array elements directly.

Consider simplifying with an immutable update:

 if (integration.type === IntegrationsType.Ai) {
-  aiIntegrations.value = aiIntegrations.value.map((i) => {
-    if (i.id === integration.id) {
-      i.is_default = true
-    } else {
-      i.is_default = false
-    }
-    return i
-  })
+  aiIntegrations.value = aiIntegrations.value.map((i) => ({
+    ...i,
+    is_default: i.id === integration.id
+  }))
 }

Likely invalid or redundant comment.


229-238: 🛠️ Refactor suggestion

Use immutable updates for Vue.js reactivity

The current implementation mutates array elements directly, which can lead to reactivity issues in Vue.js.

Consider using an immutable update pattern:

 if (integration.type === IntegrationsType.Ai) {
-  aiIntegrations.value = aiIntegrations.value.map((i) => {
-    if (i.id === integration.id) {
-      i.title = integration.title
-    }
-    return i
-  })
+  aiIntegrations.value = aiIntegrations.value.map((i) => 
+    i.id === integration.id 
+      ? { ...i, title: integration.title }
+      : i
+  )
 }

Likely invalid or redundant comment.

packages/nc-gui/composables/useNocoAi.ts (2)

347-347: LGTM!

The new method is properly exported and maintains consistent ordering with other exported functions.


20-21: Verify the safety of using Partial

The type change to Partial<IntegrationType>[] makes the type more flexible but could potentially hide missing required fields at runtime. Please ensure that all necessary fields are properly validated before use.

✅ Verification successful

Let me gather more context about the IntegrationType and its usage.


Let me search for the IntegrationType definition and usage patterns.


Let me search for more context about how aiIntegrations is used and populated.


Based on the gathered context, I can now generate the final response:

The use of Partial is safe and appropriate

The type change to Partial<IntegrationType>[] is justified as the AI integrations are used primarily for validation and UI purposes where only a subset of fields (id, title, sub_type) are required. This is evidenced by:

  1. Usage in validation: ncIsArrayIncludes(aiIntegrations, integrationId, 'id') only needs the id field
  2. UI rendering: Only id, title, and sub_type fields are accessed in components
  3. Consistent usage: All mutations (filter, map, push) maintain these essential fields
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usage of aiIntegrations to verify field access patterns
ast-grep --pattern 'aiIntegrations.value.$_'

Length of output: 652


Script:

#!/bin/bash
# Search for IntegrationType definition and its usage
ast-grep --pattern 'type IntegrationType = $_'

# Search for where aiIntegrations are populated
rg "aiIntegrations.value =" -B 2 -A 2

Length of output: 65764


Script:

#!/bin/bash
# Search for IntegrationType interface/type definition
rg "interface IntegrationType" -A 5

# Search for where aiIntegrations are populated with actual values
rg "aiIntegrations.value = " -B 2 -A 2

Length of output: 1413


Script:

#!/bin/bash
# Search for IntegrationType usage and imports
rg "IntegrationType" -B 2 -A 2

# Search for aiIntegrations usage
rg "aiIntegrations" -B 2 -A 2

Length of output: 27038

packages/nocodb/src/utils/dataConversion.ts (1)

135-149: ⚠️ Potential issue

Address potential SQL injection risk in MSSQL query

The MSSQL block constructs the JSON string using string concatenation, which can lead to SQL injection vulnerabilities. Use parameter binding instead to ensure safety.

Apply this diff to use parameter binding:

        await sqlClient.raw(
          `UPDATE ??
-            SET ?? = JSON_QUERY('{"value":' + ?? + ',"lastModifiedBy":' + ? + ',"lastModifiedTime":' + ? + ',"isStale":' + ? + '}')
+            SET ?? = JSON_QUERY(?)
            WHERE ?? is not null;`,
          [
            baseModel.getTnPath(table.table_name),
            column.column_name,
-           column.column_name,
-           commonRecord.lastModifiedBy.toString(),
-           commonRecord.lastModifiedTime.toString(),
-           commonRecord.isStale,
+           JSON.stringify({
+             value: sqlClient.raw('??', [column.column_name]),
+             lastModifiedBy: commonRecord.lastModifiedBy.toString(),
+             lastModifiedTime: commonRecord.lastModifiedTime.toString(),
+             isStale: commonRecord.isStale,
+           }),
            column.column_name,
          ],
        );

This change ensures that the parameters are safely bound and reduces the risk of SQL injection.

packages/nocodb/src/services/columns.service.ts (2)

1606-1617: 🛠️ Refactor suggestion

Optimize regular expression to prevent potential performance issues

The regular expression /{(.*?)}/g used in replace can lead to performance issues due to catastrophic backtracking. Refine the regex to prevent this.

Apply this diff:

-              prompt = colBody.prompt_raw.replace(/{(.*?)}/g, (match, p1) => {
+              prompt = colBody.prompt_raw.replace(/{([^{}]+)}/g, (match, p1) => {

This modification ensures that placeholder patterns are matched correctly without introducing performance issues.


2289-2300: 🛠️ Refactor suggestion

Optimize regular expression to prevent potential performance issues

The same issue exists here with the regular expression /{(.*?)}/g. Refine it to avoid potential catastrophic backtracking.

Apply this diff:

-                  prompt = colBody.prompt_raw.replace(/{(.*?)}/g, (match, p1) => {
+                  prompt = colBody.prompt_raw.replace(/{([^{}]+)}/g, (match, p1) => {

This change prevents potential performance issues by ensuring proper matching of placeholders.

packages/nocodb/src/models/LongTextColumn.ts (2)

61-61: Replace 'this' with class name in static method

In static methods, using this can be unclear. Use the class name LongTextColumn instead.

Apply this diff:

-        return this.read(context, longTextColumn.fk_column_id, ncMeta);
+        return LongTextColumn.read(context, longTextColumn.fk_column_id, ncMeta);
🧰 Tools
🪛 Biome (1.9.4)

[error] 61-61: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


85-85: Replace 'this' with class name in static method

Replace this with LongTextColumn for better clarity in the static method.

Apply this diff:

-        return column ? this.castType(column) : null;
+        return column ? LongTextColumn.castType(column) : null;
🧰 Tools
🪛 Biome (1.9.4)

[error] 85-85: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

packages/nc-gui/components/smartsheet/Cell.vue (1)

212-263: Clean implementation of conditional rendering using cellType!

The template changes effectively utilize the new cellType computed property for conditional rendering of cell components. Each component is properly configured with necessary props and events.

Let's verify that all cell components are properly imported:

✅ Verification successful

The previous script didn't show clear results. Let's verify the components directory structure and existence of the cell components with a more targeted search. I'm specifically looking for Vue component files in the cells directory since that's a common pattern for organizing such components.


Let's try a more basic search to locate these cell components and understand their organization within the project structure. The previous attempts had issues with file type recognition, so we'll use a more straightforward approach.


We need to verify how these LazyCell components are being imported since they're not directly visible in the components directory. They might be dynamically imported or defined elsewhere in the project.


We need to see the full content of the Cell.vue file to understand how these lazy components are being handled, since we haven't found explicit imports. They might be using Vue's built-in lazy loading syntax or a custom implementation.


Lazy-loaded components are correctly implemented using Vue's built-in lazy loading

The implementation is correct and follows Vue's best practices. The Lazy prefix in component names indicates they are being lazy-loaded using Vue's built-in lazy loading mechanism. The conditional rendering based on cellType is clean and well-organized, with each component being loaded only when needed. The components are automatically registered through Vue's auto-import feature, which is a common pattern in modern Vue applications.

Key observations:

  • The cellType computed property correctly determines which component to render based on column type
  • Each component is prefixed with Lazy indicating proper lazy loading
  • Components are conditionally rendered using v-else-if for optimal performance
  • Props and events are consistently passed to all components
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all cell components referenced in the template exist
# Test: Search for all LazyCell components. Expect: Component files exist for each type.

# Get all LazyCell components from the template
rg -o 'LazyCell\w+' packages/nc-gui/components/smartsheet/Cell.vue | sort -u | while read -r component; do
  # Search for corresponding component files
  fd "$component.vue" packages/nc-gui/components
done

Length of output: 1839


Script:

#!/bin/bash
# Let's try a different approach to verify the existence of these components
# Search for all Lazy cell components in the components directory
rg --type vue "^<template" -l packages/nc-gui/comp
10000
onents/smartsheet/cells/

Length of output: 104


Script:

#!/bin/bash
# Let's try a simpler approach to find the cell components
# First, let's check if the cells directory exists and list its contents
fd -t f . packages/nc-gui/components/smartsheet/ --full-path | grep -i "cell.*\.vue"

Length of output: 616


Script:

#!/bin/bash
# Let's check the imports in Cell.vue to see where these lazy components are defined
rg "import.*LazyCell.*from" packages/nc-gui/components/smartsheet/Cell.vue

# Also check for dynamic imports using defineAsyncComponent
rg "defineAsyncComponent|import\(.*LazyCell" packages/nc-gui/components/smartsheet/Cell.vue

Length of output: 170


Script:

#!/bin/bash
# Let's check the entire Cell.vue file to understand the component setup
cat packages/nc-gui/components/smartsheet/Cell.vue

Length of output: 10840

packages/nc-gui/components/smartsheet/column/LongTextOptions.vue (1)

Line range hint 1-361: Localization improvements needed

Several user-facing strings still need to be wrapped with the localization function for internationalization support.

This was previously noted in an earlier review and remains applicable. Please refer to the previous comment for the specific changes needed.

packages/nc-gui/components/smartsheet/header/Menu.vue (2)

Line range hint 451-465: LGTM: Improved UI feedback for invalid columns

The template changes enhance user feedback by displaying validation state and tooltips appropriately.


48-61: Verify AI integration validation logic

The new computed property columnInvalid evaluates column validity using isColumnInvalid function. This is a critical validation that affects UI feedback.

✅ Verification successful

AI Integration validation logic is correctly implemented

The isColumnInvalid function implementation in columnUtils.ts properly validates columns based on their UI types, with specific handling for AI-related features:

  • For Button columns with AI actions, it validates the presence of AI integration ID and checks if the integration exists
  • For LongText columns with AI features, it verifies the AI integration configuration
  • The function correctly uses the aiIntegrations and isReadOnly parameters as passed from the Menu component
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify the isColumnInvalid function implementation
ast-grep --pattern 'function isColumnInvalid($column, $aiIntegrations, $isPublic) {
  $$$
}'

Length of output: 94


Script:

#!/bin/bash
# Let's try to find the isColumnInvalid function with a broader search
rg "isColumnInvalid" -A 10

Length of output: 3290


Script:

#!/bin/bash
# Let's examine the full implementation of isColumnInvalid function
cat packages/nc-gui/utils/columnUtils.ts

Length of output: 9978

packages/nocodb/src/db/formulav2/formulaQueryBuilderv2.ts (2)

5-5: Verify LongTextAiMetaProp usage

Ensure the imported LongTextAiMetaProp constant is correctly defined and used consistently across the codebase.

✅ Verification successful

LongTextAiMetaProp is consistently defined and used

The constant LongTextAiMetaProp is properly defined in packages/nocodb-sdk/src/lib/globals.ts as 'ai' and is consistently imported and used across the codebase for:

  • Identifying AI-enabled long text columns
  • Handling AI-specific column metadata
  • Managing column options and UI rendering
  • Processing data during import/export operations
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check LongTextAiMetaProp usage
rg "LongTextAiMetaProp" -A 2

Length of output: 6843


832-872: Verify database-specific JSON extraction implementations

The implementation adds database-specific JSON value extraction for AI-enabled LongText fields. Each database type has its own SQL syntax:

  • PostgreSQL: TRIM('"' FROM (??::jsonb->>'value'))
  • MySQL: JSON_UNQUOTE(JSON_EXTRACT(??, '$.value'))
  • SQLite: json_extract(??, '$.value')
  • MSSQL: JSON_VALUE(??, '$.value')
✅ Verification successful

Database-specific JSON extraction implementations are consistent and verified

The implementation of JSON value extraction for AI-enabled LongText fields is consistent across the codebase. The same patterns are used in multiple components:

  • formulaQueryBuilderv2.ts
  • sortV2.ts
  • conditionV2.ts
  • dataConversion.ts

The SQL syntax for each database type is correctly implemented:

  • PostgreSQL: Uses TRIM('"' FROM (??::jsonb->>'value')) to handle JSONB type
  • MySQL: Uses JSON_UNQUOTE(JSON_EXTRACT(??, '$.value')) with proper JSON validation
  • SQLite: Uses json_extract(??, '$.value') for basic JSON extraction
  • MSSQL: Uses JSON_VALUE(??, '$.value') with ISJSON validation

The implementation is also properly integrated with the AI feature flag (LongTextAiMetaProp) across the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify JSON extraction implementations across database types
ast-grep --pattern 'case UITypes.LongText: {
  $$$
  if (col.meta?.[LongTextAiMetaProp] === true) {
    $$$
  }
  $$$
}'

Length of output: 122


Script:

#!/bin/bash
# Let's try a different approach to verify the JSON extraction implementations
# First, let's check if there are any test files related to this functionality
fd -t f test.*\.(js|ts) --exec rg -l "LongText.*JSON"

# Also search for any related database-specific implementations
rg -A 2 "JSON_(UNQUOTE|EXTRACT|VALUE)" 

# And check for PostgreSQL jsonb specific syntax
rg -A 2 "jsonb->>'value'"

Length of output: 236


Script:

#!/bin/bash
# Let's try a simpler approach to verify the implementations
# Search for test files
fd -t f "test" -e ts -e js | xargs rg -l "LongText.*JSON"

# Search for database-specific JSON implementations
rg "JSON_UNQUOTE|JSON_EXTRACT|JSON_VALUE|jsonb->>'value'" -A 2

# Search for the LongTextAiMetaProp usage
rg "LongTextAiMetaProp" -A 5

Length of output: 19550

packages/nc-gui/components/smartsheet/column/EditOrAdd.vue (2)

Line range hint 267-285: LGTM: AI prompt type selection logic is well-implemented

The implementation correctly handles:

  • Type conversion from AIPrompt to LongText
  • Metadata setting for AI prompt columns
  • Proper preload configuration

981-981: LGTM: Button state handling is correct

The disabled state correctly depends on form validation and saving state.

packages/nocodb/src/db/conditionV2.ts (1)

596-612: LGTM: Database-specific JSON handling is well-implemented

The implementation correctly handles JSON field extraction across different databases:

  • PostgreSQL: Uses jsonb->>'value' with proper quote trimming
  • MySQL: Uses JSON_UNQUOTE(JSON_EXTRACT)
  • SQLite: Uses json_extract
  • MSSQL: Uses JSON_VALUE
packages/nocodb/src/models/Column.ts (3)

1353-1369: Handle LongText AI column updates consistently

In the update logic for UITypes.LongText, ensure that any associated AI metadata is appropriately updated or deleted when the column is modified. This prevents orphaned AI configurations and maintains data integrity.


1961-1974: LGTM: Bulk insertion logic for LongText AI columns is well-implemented

The implementation correctly handles:

  • AI metadata check
  • Required field population
  • Error state handling

921-925: ⚠️ Potential issue

Use optional chaining to prevent potential runtime error

The condition if (ai.prompt && ai.prompt.match(/{column_id}/)) could cause a runtime error if ai.prompt is null or undefined.

Apply this diff to fix the issue:

-if (ai.prompt && ai.prompt.match(/{column_id}/)) {
+if (ai.prompt?.match(/{column_id}/)) {

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome (1.9.4)

[error] 921-921: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

packages/nocodb/src/modules/jobs/jobs/export-import/import.service.ts (5)

182-182: LGTM: AI prompt column filtering

The addition of !isAIPromptCol(a) in the filter condition ensures AI prompt columns are excluded from the reduced column set during import, which is consistent with the handling of other special column types.


1288-1296: LGTM: AI prompt column creation

The column creation logic for AI prompt columns correctly handles the essential properties:

  • Integration ID
  • Model
  • Prompt raw content

1281-1287: Verify workspace ID validation for AI prompt columns

Similar to button columns, the workspace ID validation for AI prompt columns ensures proper nullification of workspace-specific properties when workspace IDs don't match.

✅ Verification successful

Workspace ID validation for AI prompt columns is correctly implemented

The code shows consistent handling of workspace ID validation between Button and AI prompt columns. When workspace IDs don't match, both column types properly nullify the workspace-specific properties (fk_workspace_id, fk_integration_id, and model). This implementation ensures data integrity during import operations across different workspaces.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify consistent workspace ID validation for AI columns
# Test: Search for workspace ID validations in AI-related code
rg -A 5 "isAIPromptCol.*fk_workspace_id"

Length of output: 42


Script:

#!/bin/bash
# Let's first check for the isAIPromptCol function definition and its usage
ast-grep --pattern 'function isAIPromptCol($_) { $$$ }'

# Also search for any AI prompt column related code
rg -l "AIPromptCol|ai.*prompt"

# Check for workspace ID validations in general
rg "fk_workspace_id.*!=="

Length of output: 2678


Script:

#!/bin/bash
# Let's check the context around both workspace ID validations in import.service.ts
rg -B 5 -A 5 "base.fk_workspace_id !== colOptions.fk_workspace_id" packages/nocodb/src/modules/jobs/jobs/export-import/import.service.ts

Length of output: 806


1262-1270: Ensure proper handling of output column IDs

The mapping of output column IDs through idMap before joining ensures proper reference integrity during import.

✅ Verification successful

Let me gather more information about the getIdOrExternalId function and its usage in the context of output column IDs.


Let me search for the definition of getIdOrExternalId specifically in the import service file since it seems to be locally defined.


Proper handling of output column IDs confirmed

The code correctly handles output column IDs during import by:

  1. Using getIdOrExternalId function which maps old IDs to new IDs using either idMap or externalIdMap
  2. Properly splitting, mapping, and joining the IDs while maintaining referential integrity
  3. Consistent with the pattern used throughout the import service for handling other column references
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify output column ID handling
# Test: Search for other instances of output column ID handling
rg -A 5 "output_column_ids.*join"

Length of output: 1116


Script:

#!/bin/bash
# Search for getIdOrExternalId function definition and usage
ast-grep --pattern 'function getIdOrExternalId($_) { $$$ }'

# Search for other instances where output_column_ids are processed during import
rg -A 5 "output_column_ids.*split|output_column_ids.*map"

Length of output: 4153


Script:

#!/bin/bash
# Search for getIdOrExternalId in the import service file
cat packages/nocodb/src/modules/jobs/jobs/export-import/import.service.ts | grep -A 10 "getIdOrExternalId"

Length of output: 18899


1244-1248: Verify workspace ID validation for button columns

The workspace ID validation for button columns ensures proper nullification of workspace-specific properties when the workspace IDs don't match. This prevents potential data leakage between workspaces.

✅ Verification successful

Let me gather more context about the column types and their workspace validation patterns.


Let me verify the implementation of these column types to understand their workspace-specific properties better.


Let me search for the implementation of Button and AI Prompt columns to understand their workspace-specific properties better.


Let me search specifically for the Button and AI Prompt column implementations and their workspace-related security measures.


Based on the comprehensive analysis of the codebase, I can now generate the final response.

Workspace ID validation for Button and AI Prompt columns is correctly implemented

The workspace ID validation for both Button and AI Prompt columns ensures proper security by:

  • Nullifying workspace-specific properties (workspace_id, integration_id, model) when workspace IDs don't match
  • This prevents potential data leakage between workspaces during import/export operations
  • The validation is consistently implemented across both column types in the same way
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify workspace ID validation is consistent across the codebase
# Test: Search for similar workspace ID validations in other column types
rg -A 5 "fk_workspace_id !== .+?.fk_workspace_id"

Length of output: 1304


Script:

#!/bin/bash
# Search for the context around these workspace ID validations to understand the column types
rg -B 10 -A 5 "fk_workspace_id !== colOptions.fk_workspace_id" packages/nocodb/src/modules/jobs/jobs/export-import/import.service.ts

Length of output: 1086


Script:

#!/bin/bash
# Search for Button and AI Prompt column type definitions and their properties
ast-grep --pattern 'interface $_ {
  $$$
  fk_workspace_id?: $_
  $$$
}'

# Also check for any potential security-related validations
rg -B 5 "fk_workspace_id" --type ts

Length of output: 66803


Script:

#!/bin/bash
# Search for Button and AI Prompt column implementations
ast-grep --pattern 'class $_ {
  $$$
  fk_workspace_id?: $_
  $$$
}'

# Also check for any security-related validations around these column types
rg -B 5 "UITypes.Button|isAIPromptCol" --type ts

Length of output: 65891


Script:

#!/bin/bash
# Search for Button and AI Prompt column implementations and their security validations
rg -B 10 -A 10 "UITypes.Button|isAIPromptCol" --type ts

# Also check for any workspace-related security validations
rg -B 5 "fk_workspace_id !== .+?.fk_workspace_id" --type ts

Length of output: 71315

packages/nc-gui/components/smartsheet/details/Fields.vue (1)

1040-1043: LGTM: Added delay for copy field URL feedback

The addition of a 5-second delay before resetting isFieldIdCopied provides better user feedback after copying a field ID.

packages/nocodb/src/db/BaseModelSqlv2.ts (3)

10063-10104: LGTM: Well-structured AI prompt column handling

The implementation for AI prompt columns is well-designed with:

  • Proper type checking and validation
  • Clear separation between system and user modifications
  • Comprehensive metadata tracking including lastModified info
  • Proper state management with isStale flag

5721-5724: ⚠️ Potential issue

Ensure promises are properly awaited in asynchronous operations

The current implementation may lead to unhandled promises and race conditions since the async operations are not properly awaited.

Apply this diff to properly handle the promises:

-          insertDatas.map(
+          await Promise.all(insertDatas.map(
            async (d) =>
              await this.prepareNocoData(d, true, cookie, null, { raw }),
-          ),
+          )),

Likely invalid or redundant comment.


8636-8654: 🛠️ Refactor suggestion

Add error handling for JSON parsing failures

Empty catch blocks silently swallow errors which makes debugging difficult. Consider logging the error or handling it appropriately.

Apply this diff to improve error handling:

          try {
            d[col.id] = JSON.parse(d[col.id]);
-         } catch {}
+         } catch (e) {
+           console.error(`Error parsing JSON for column ${col.id}:`, e);
+           // Keep the original value if parsing fails
+           d[col.id] = d[col.id];
+         }

Likely invalid or redundant comment.

Comment on lines +24 to +28
const isAiIntegrationAvailableInList = (integrationId?: string) => {
if (!aiIntegrationAvailable.value) return false

const { listIntegrationByType } = useProvideIntegrationViewStore()
return ncIsArrayIncludes(aiIntegrations.value, integrationId, 'id')
}
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Import missing and method name could be improved

  1. The ncIsArrayIncludes helper is not imported in useNocoAi.ts. Please add the following import:
    import { ncIsArrayIncludes } from '~/utils/is'
  2. Consider renaming isAiIntegrationAvailableInList to hasAiIntegration for better readability and conciseness.
🔗 Analysis chain

Verify helper import and consider method name refinement

  1. Please ensure that ncIsArrayIncludes helper is properly imported as it's not visible in the current context.
  2. Consider a more concise name like hasAiIntegration instead of isAiIntegrationAvailableInList.

Let me verify the import by checking the imports in the file.


Let me check the implementation of ncIsArrayIncludes since I can see it's not imported in the file.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for ncIsArrayIncludes import and implementation
rg "ncIsArrayIncludes"

Length of output: 1847


Script:

#!/bin/bash
# Check imports in useNocoAi.ts
cat packages/nc-gui/composables/useNocoAi.ts

Length of output: 9103


Script:

#!/bin/bash
# Check the implementation and exports in is.ts
cat packages/nc-gui/utils/is.ts

Length of output: 5280

Comment on lines +159 to +187
const tooltipInstances: any[] = []

function loadMentionFieldTagTooltip() {
document.querySelectorAll('.nc-ai-prompt-with-fields .prompt-field-tag').forEach((el) => {
const tooltip = Object.values(el.attributes).find((attr) => attr.name === 'data-tooltip')
if (!tooltip || el.scrollWidth <= el.clientWidth) return
// Show tooltip only on truncate
const instance = tippy(el, {
content: `<div class="tooltip text-xs">${tooltip.value}</div>`,
placement: 'top',
allowHTML: true,
arrow: true,
animation: 'fade',
duration: 0,
maxWidth: '200px',
})

tooltipInstances.push(instance)
})
}

onMounted(() => {
debouncedLoadMentionFieldTagTooltip()
})

onBeforeUnmount(() => {
tooltipInstances.forEach((instance) => instance?.destroy())
tooltipInstances.length = 0
})
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Potential memory leak in tooltip management

The tooltip instances array is maintained in component scope, which could lead to memory leaks if the component is repeatedly mounted/unmounted. Consider using a WeakMap or ensuring proper cleanup.

-const tooltipInstances: any[] = []
+const tooltipInstances = new WeakMap()

 function loadMentionFieldTagTooltip() {
   document.querySelectorAll('.nc-ai-prompt-with-fields .prompt-field-tag').forEach((el) => {
     const tooltip = Object.values(el.attributes).find((attr) => attr.name === 'data-tooltip')
     if (!tooltip || el.scrollWidth <= el.clientWidth) return
-    const instance = tippy(el, {
+    let instance = tooltipInstances.get(el)
+    if (instance) {
+      instance.destroy()
+    }
+    instance = tippy(el, {
       content: `<div class="tooltip text-xs">${tooltip.value}</div>`,
       placement: 'top',
       allowHTML: true,
       arrow: true,
       animation: 'fade',
       duration: 0,
       maxWidth: '200px',
     })
-    tooltipInstances.push(instance)
+    tooltipInstances.set(el, instance)
   })
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const tooltipInstances: any[] = []
function loadMentionFieldTagTooltip() {
document.querySelectorAll('.nc-ai-prompt-with-fields .prompt-field-tag').forEach((el) => {
const tooltip = Object.values(el.attributes).find((attr) => attr.name === 'data-tooltip')
if (!tooltip || el.scrollWidth <= el.clientWidth) return
// Show tooltip only on truncate
const instance = tippy(el, {
content: `<div class="tooltip text-xs">${tooltip.value}</div>`,
placement: 'top',
allowHTML: true,
arrow: true,
animation: 'fade',
duration: 0,
maxWidth: '200px',
})
tooltipInstances.push(instance)
})
}
onMounted(() => {
debouncedLoadMentionFieldTagTooltip()
})
onBeforeUnmount(() => {
tooltipInstances.forEach((instance) => instance?.destroy())
tooltipInstances.length = 0
})
const tooltipInstances = new WeakMap()
function loadMentionFieldTagTooltip() {
document.querySelectorAll('.nc-ai-prompt-with-fields .prompt-field-tag').forEach((el) => {
const tooltip = Object.values(el.attributes).find((attr) => attr.name === 'data-tooltip')
if (!tooltip || el.scrollWidth <= el.clientWidth) return
let instance = tooltipInstances.get(el)
if (instance) {
instance.destroy()
}
instance = tippy(el, {
content: `<div class="tooltip text-xs">${tooltip.value}</div>`,
placement: 'top',
allowHTML: true,
arrow: true,
animation: 'fade',
duration: 0,
maxWidth: '200px',
})
tooltipInstances.set(el, instance)
})
}
onMounted(() => {
debouncedLoadMentionFieldTagTooltip()
})
onBeforeUnmount(() => {
tooltipInstances.forEach((instance) => instance?.destroy())
tooltipInstances.length = 0
})

Comment on lines +269 to +315
const isColumnInvalid = (
col: ColumnType,
aiIntegrations: Partial<IntegrationType>[] = [],
isReadOnly: boolean = false,
): { isInvalid: boolean; tooltip: string } => {
const result = {
isInvalid: false,
tooltip: 'msg.invalidColumnConfiguration',
}

switch (col.uidt) {
case UITypes.Formula:
return !!(col.colOptions as FormulaType).error
result.isInvalid = !!(col.colOptions as FormulaType).error
break
case UITypes.Button: {
const colOptions = col.colOptions as ButtonType
if (colOptions.type === ButtonActionsType.Webhook) {
return !colOptions.fk_webhook_id
result.isInvalid = !colOptions.fk_webhook_id
} else if (colOptions.type === ButtonActionsType.Url) {
return !!colOptions.error
result.isInvalid = !!colOptions.error
} else if (colOptions.type === ButtonActionsType.Ai) {
result.isInvalid =
!colOptions.fk_integration_id ||
(isReadOnly
? false
: !!colOptions.fk_integration_id && !ncIsArrayIncludes(aiIntegrations, colOptions.fk_integration_id, 'id'))
result.tooltip = 'title.aiIntegrationMissing'
}
break
}
}
case UITypes.LongText: {
if (parseProp(col.meta)[LongTextAiMetaProp]) {
const colOptions = col.colOptions as ButtonType

result.isInvalid =
!colOptions.fk_integration_id ||
(isReadOnly
? false
: !!colOptions.fk_integration_id && !ncIsArrayIncludes(aiIntegrations, colOptions.fk_integration_id, 'id'))

if (col.uidt === UITypes.Formula) {
return !!(col.colOptions as FormulaType).error
result.tooltip = 'title.aiIntegrationMissing'
}
break
}
}

return result
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Simplify column validation logic

The validation logic in isColumnInvalid could be simplified using a strategy pattern for better maintainability.

+type ValidationStrategy = (col: ColumnType, aiIntegrations: Partial<IntegrationType>[], isReadOnly: boolean) => {
+  isInvalid: boolean
+  tooltip: string
+}

+const validationStrategies: Record<string, ValidationStrategy> = {
+  [UITypes.Formula]: (col) => ({
+    isInvalid: !!(col.colOptions as FormulaType).error,
+    tooltip: 'msg.invalidColumnConfiguration'
+  }),
+  [UITypes.Button]: (col, aiIntegrations, isReadOnly) => {
+    const colOptions = col.colOptions as ButtonType
+    switch (colOptions.type) {
+      case ButtonActionsType.Webhook:
+        return {
+          isInvalid: !colOptions.fk_webhook_id,
+          tooltip: 'msg.invalidColumnConfiguration'
+        }
+      case ButtonActionsType.Url:
+        return {
+          isInvalid: !!colOptions.error,
+          tooltip: 'msg.invalidColumnConfiguration'
+        }
+      case ButtonActionsType.Ai:
+        return {
+          isInvalid: !colOptions.fk_integration_id || 
+            (!isReadOnly && !ncIsArrayIncludes(aiIntegrations, colOptions.fk_integration_id, 'id')),
+          tooltip: 'title.aiIntegrationMissing'
+        }
+      default:
+        return { isInvalid: false, tooltip: '' }
+    }
+  }
+}

 const isColumnInvalid = (
   col: ColumnType,
   aiIntegrations: Partial<IntegrationType>[] = [],
   isReadOnly: boolean = false,
 ): { isInvalid: boolean; tooltip: string } => {
-  const result = {
+  return validationStrategies[col.uidt]?.(col, aiIntegrations, isReadOnly) ?? {
     isInvalid: false,
     tooltip: 'msg.invalidColumnConfiguration',
   }
-
-  switch (col.uidt) {
-    // ... existing switch cases
-  }
-
-  return result
 }

Committable suggestion skipped: line range outside the PR's diff.

@mertmit mertmit merged commit 818d934 into develop Dec 9, 2024
22 of 23 checks passed
@mertmit mertmit deleted the chore/preps branch December 9, 2024 08:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
lgtm This PR has been approved by a maintainer size:XL This PR changes 500-999 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
0