Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2252,6 +2252,7 @@
"InvalidTableStructureChanges": "Check the table structure changes.",
"InvalidIndexDefinition": "Complete the index name and column selection.",
"InvalidCsvFile": "The CSV file is invalid or cannot be read.",
"CopyOperationFailedDescription": "The selected data could not be copied."
"CopyOperationFailedDescription": "The selected data could not be copied.",
"TableWithoutPrimaryKeyNotEditable": "This table has no primary key, so adding, updating, or deleting data is not supported yet."
}
}
3 changes: 2 additions & 1 deletion i18n/locales/es.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"Monitor": {
"Unavailable": "La sesión ha finalizado o no se puede supervisar.",

Check warning on line 3 in i18n/locales/es.json

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"supervisar" should be "supervisor".

Check warning on line 3 in i18n/locales/es.json

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"supervisar" should be "supervisor".
"PauseSent": "Se ha enviado la tarea de pausa",
"ResumeSent": "Se ha enviado la tarea de reanudación"
},
Expand All @@ -14,13 +14,13 @@
"Play": "Reproducir",
"Pause": "Pausar",
"Restart": "Reiniciar",
"HistoryCommands": "Historial de comandos",

Check warning on line 17 in i18n/locales/es.json

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"comandos" should be "commandos".

Check warning on line 17 in i18n/locales/es.json

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"Historial" should be "Historical".

Check warning on line 17 in i18n/locales/es.json

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"comandos" should be "commandos".

Check warning on line 17 in i18n/locales/es.json

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"Historial" should be "Historical".
"Playlist": "Lista de reproducción",
"SearchCommands": "Buscar comandos...",

Check warning on line 19 in i18n/locales/es.json

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"comandos" should be "commandos".

Check warning on line 19 in i18n/locales/es.json

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"comandos" should be "commandos".
"NoCommands": "No hay registros de comandos",

Check warning on line 20 in i18n/locales/es.json

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"comandos" should be "commandos".

Check warning on line 20 in i18n/locales/es.json

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"comandos" should be "commandos".
"NoCommandsHint": "Esta sesión no tiene comandos grabados",

Check warning on line 21 in i18n/locales/es.json

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"comandos" should be "commandos".

Check warning on line 21 in i18n/locales/es.json

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"comandos" should be "commandos".
"CommandsFailed": "No se pudieron cargar los comandos",

Check warning on line 22 in i18n/locales/es.json

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"comandos" should be "commandos".

Check warning on line 22 in i18n/locales/es.json

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"comandos" should be "commandos".
"CommandsFailedHint": "El historial de comandos no está disponible temporalmente",

Check warning on line 23 in i18n/locales/es.json

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"comandos" should be "commandos".

Check warning on line 23 in i18n/locales/es.json

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"historial" should be "historical".

Check warning on line 23 in i18n/locales/es.json

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"comandos" should be "commandos".

Check warning on line 23 in i18n/locales/es.json

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"historial" should be "historical".
"Loading": "Cargando...",
"HideRail": "Ocultar panel",
"ShowRail": "Mostrar panel",
Expand All @@ -34,7 +34,7 @@
"UnsupportedHint": "Este tipo de grabación no es compatible con el reproductor en línea.",
"Reload": "Volver a cargar",
"DesktopBlocked": "Solo en el navegador",
"DesktopBlockedHint": "La reproducción de sesiones solo está disponible en un navegador web. Copie el enlace y ábralo allí.",

Check warning on line 37 in i18n/locales/es.json

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"Copie" should be "Copied" or "Copier" or "Copies" or "Copy".

Check warning on line 37 in i18n/locales/es.json

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"Copie" should be "Copied" or "Copier" or "Copies" or "Copy".
"ShortcutsTitle": "Atajos de teclado",
"ShortcutPlayPause": "pausar / reanudar",
"ShortcutFullscreen": "alternar el modo de pantalla completa",
Expand Down Expand Up @@ -2252,6 +2252,7 @@
"InvalidTableStructureChanges": "Check the table structure changes.",
"InvalidIndexDefinition": "Complete the index name and column selection.",
"InvalidCsvFile": "The CSV file is invalid or cannot be read.",
"CopyOperationFailedDescription": "The selected data could not be copied."
"CopyOperationFailedDescription": "The selected data could not be copied.",
"TableWithoutPrimaryKeyNotEditable": "Esta tabla no tiene clave primaria; de momento no se pueden añadir, modificar ni eliminar datos."
}
}
3 changes: 2 additions & 1 deletion i18n/locales/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -2252,6 +2252,7 @@
"InvalidTableStructureChanges": "Check the table structure changes.",
"InvalidIndexDefinition": "Complete the index name and column selection.",
"InvalidCsvFile": "The CSV file is invalid or cannot be read.",
"CopyOperationFailedDescription": "The selected data could not be copied."
"CopyOperationFailedDescription": "The selected data could not be copied.",
"TableWithoutPrimaryKeyNotEditable": "このテーブルには主キーが設定されていないため、データの追加・変更・削除は現在サポートされていません。"
}
}
3 changes: 2 additions & 1 deletion i18n/locales/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -2252,6 +2252,7 @@
"InvalidTableStructureChanges": "Check the table structure changes.",
"InvalidIndexDefinition": "Complete the index name and column selection.",
"InvalidCsvFile": "The CSV file is invalid or cannot be read.",
"CopyOperationFailedDescription": "The selected data could not be copied."
"CopyOperationFailedDescription": "The selected data could not be copied.",
"TableWithoutPrimaryKeyNotEditable": "이 테이블에는 기본 키가 없어 지금은 데이터를 추가, 수정 또는 삭제할 수 없습니다."
}
}
3 changes: 2 additions & 1 deletion i18n/locales/pt_br.json
Original file line number Diff line number Diff line change
Expand Up @@ -2252,6 +2252,7 @@
"InvalidTableStructureChanges": "Check the table structure changes.",
"InvalidIndexDefinition": "Complete the index name and column selection.",
"InvalidCsvFile": "The CSV file is invalid or cannot be read.",
"CopyOperationFailedDescription": "The selected data could not be copied."
"CopyOperationFailedDescription": "The selected data could not be copied.",
"TableWithoutPrimaryKeyNotEditable": "Esta tabela não possui chave primária; por enquanto não é possível adicionar, alterar ou excluir dados."
}
}
3 changes: 2 additions & 1 deletion i18n/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -2252,6 +2252,7 @@
"InvalidTableStructureChanges": "Check the table structure changes.",
"InvalidIndexDefinition": "Complete the index name and column selection.",
"InvalidCsvFile": "The CSV file is invalid or cannot be read.",
"CopyOperationFailedDescription": "The selected data could not be copied."
"CopyOperationFailedDescription": "The selected data could not be copied.",
"TableWithoutPrimaryKeyNotEditable": "У этой таблицы не задан первичный ключ, поэтому добавление, изменение и удаление данных пока не поддерживается."
}
}
3 changes: 2 additions & 1 deletion i18n/locales/vi.json
Original file line number Diff line number Diff line change
Expand Up @@ -2252,6 +2252,7 @@
"InvalidTableStructureChanges": "Check the table structure changes.",
"InvalidIndexDefinition": "Complete the index name and column selection.",
"InvalidCsvFile": "The CSV file is invalid or cannot be read.",
"CopyOperationFailedDescription": "The selected data could not be copied."
"CopyOperationFailedDescription": "The selected data could not be copied.",
"TableWithoutPrimaryKeyNotEditable": "Bảng hiện tại chưa có khóa chính, tạm thời không hỗ trợ thêm, sửa hoặc xóa dữ liệu."
}
}
3 changes: 2 additions & 1 deletion i18n/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -2255,6 +2255,7 @@
"InvalidTableStructureChanges": "请检查表结构更改。",
"InvalidIndexDefinition": "请完整填写索引名称并选择列。",
"InvalidCsvFile": "CSV 文件无效或无法读取。",
"CopyOperationFailedDescription": "无法复制所选数据。"
"CopyOperationFailedDescription": "无法复制所选数据。",
"TableWithoutPrimaryKeyNotEditable": "当前表未设置主键,暂不支持新增、修改或删除数据。"
}
}
3 changes: 2 additions & 1 deletion i18n/locales/zh_hant.json
Original file line number Diff line number Diff line change
Expand Up @@ -2252,6 +2252,7 @@
"InvalidTableStructureChanges": "Check the table structure changes.",
"InvalidIndexDefinition": "Complete the index name and column selection.",
"InvalidCsvFile": "The CSV file is invalid or cannot be read.",
"CopyOperationFailedDescription": "The selected data could not be copied."
"CopyOperationFailedDescription": "The selected data could not be copied.",
"TableWithoutPrimaryKeyNotEditable": "目前資料表未設定主鍵,暫不支援新增、修改或刪除資料。"
}
}
15 changes: 15 additions & 0 deletions ui/chen/components/DataViewPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import ChenWorkspaceModal from "~/chen/components/WorkspaceModal.vue";
import { useChenDataViewDerivedMeta } from "~/chen/composables/useChenDataViewDerivedMeta";
import { useChenDataViewEditing } from "~/chen/composables/useChenDataViewEditing";
import { chenGridPreferenceKey } from "~/chen/composables/useChenGridPreferences";
import { chenDataViewMissingPrimaryKey } from "~/chen/utils/dataViewEditing";
import { buildChenDropIndexSql, chenSupportsIndexDdl } from "~/chen/utils/indexSql";
import { isChenViewRelation } from "~/chen/utils/resourceTree";

Expand Down Expand Up @@ -82,6 +83,14 @@ const schemaName = computed(() => String(props.tab.meta?.schema || "").trim());
const isViewRelation = computed(() =>
isChenViewRelation({ nodeKey: props.tab.nodeKey, kind: props.tab.tableMetadata?.kind })
);
const missingPrimaryKey = computed(
() =>
!editing.editable.value &&
chenDataViewMissingPrimaryKey(props.tab.data, {
isView: isViewRelation.value,
tableMetadata: props.tab.tableMetadata
})
);
const indexDdlSupported = computed(
() =>
!isViewRelation.value &&
Expand Down Expand Up @@ -294,6 +303,12 @@ function importCsvRows(rows: Array<Record<string, string | null>>) {
</div>

<div v-if="tab.activePanel === 'data'" class="flex min-h-0 flex-1 flex-col">
<div
v-if="missingPrimaryKey"
class="border-b border-warning/20 bg-warning/10 px-3 py-1.5 text-xs text-warning"
>
{{ t("Chen.TableWithoutPrimaryKeyNotEditable") }}
</div>
<div class="flex shrink-0 items-center gap-1.5 border-b border-default px-2 py-1">
<UButton
size="xs"
Expand Down
13 changes: 13 additions & 0 deletions ui/chen/components/QueryResultTabs.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
cancelChenSaveChangesConfirmation,
chenDataViewHasDirty,
clearChenDataViewEdits,
chenDataViewMissingPrimaryKey,
isChenDataViewEditable
} from "~/chen/utils/dataViewEditing";

Expand Down Expand Up @@ -57,6 +58,12 @@ const activeResult = computed(() => {
return props.resultTabs.find((item) => item.id === props.activeResultTabId) || null;
});
const activeResultEditable = computed(() => isChenDataViewEditable(activeResult.value?.data));
const activeResultMissingPrimaryKey = computed(
() =>
props.dataViewEditing &&
!activeResultEditable.value &&
chenDataViewMissingPrimaryKey(activeResult.value?.data)
);
const activeResultDirty = computed(() =>
Boolean(activeResult.value && chenDataViewHasDirty(activeResult.value.editState))
);
Expand Down Expand Up @@ -167,6 +174,12 @@ function cancelActiveResultChanges() {
</div>

<div v-else-if="activeResult" :key="activeResult.id" class="flex min-h-0 flex-1 flex-col">
<div
v-if="activeResultMissingPrimaryKey"
class="border-b border-warning/20 bg-warning/10 px-3 py-1.5 text-xs text-warning"
>
{{ t("Chen.TableWithoutPrimaryKeyNotEditable") }}
</div>
<div class="flex shrink-0 items-center justify-between border-b border-default px-3 py-2 text-sm">
<div class="min-w-0 truncate">
{{ activeResult.title }}
Expand Down
41 changes: 41 additions & 0 deletions ui/chen/utils/dataViewEditing.noPk.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { describe, expect, it } from "vitest";

import {
chenDataViewMissingPrimaryKey,
CHEN_EDIT_REASON_NO_PRIMARY_KEY
} from "~/chen/utils/dataViewEditing";

describe("chenDataViewMissingPrimaryKey", () => {
it("detects the backend no-primary-key edit reason", () => {
expect(
chenDataViewMissingPrimaryKey({
fields: [{ name: "name", editReason: CHEN_EDIT_REASON_NO_PRIMARY_KEY }],
data: []
})
).toBe(true);
});

it("detects loaded table metadata without a primary key", () => {
expect(
chenDataViewMissingPrimaryKey(
{ fields: [{ name: "name" }], data: [] },
{ tableMetadata: { loadedSections: ["primaryKey"], primaryKey: null } }
)
).toBe(true);
});

it("does not flag views or incomplete metadata", () => {
expect(
chenDataViewMissingPrimaryKey(
{ fields: [{ name: "name" }], data: [] },
{ isView: true, tableMetadata: { loadedSections: ["primaryKey"], primaryKey: null } }
)
).toBe(false);
expect(
chenDataViewMissingPrimaryKey(
{ fields: [{ name: "name" }], data: [] },
{ tableMetadata: { loadedSections: ["columns"], primaryKey: null } }
)
).toBe(false);
});
});
20 changes: 20 additions & 0 deletions ui/chen/utils/dataViewEditing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,10 +214,30 @@ export function acceptChenSaveChangesResult(state: ChenDataViewEditState, result
return "applied" as const;
}

export const CHEN_EDIT_REASON_NO_PRIMARY_KEY = "NO_PRIMARY_KEY";

export function isChenDataViewEditable(dataset: ChenDataViewDataset | null | undefined) {
return dataset?.editable === true && dataset.fields.some((field) => field.editable === true);
}

export function chenDataViewMissingPrimaryKey(
dataset?: ChenDataViewDataset | null,
options?: {
isView?: boolean;
tableMetadata?: { loadedSections?: string[]; primaryKey?: { columns?: string[] } | null } | null;
}
) {
if (options?.isView) return false;
const fields = dataset?.fields || [];
if (fields.some((field) => field.editReason === CHEN_EDIT_REASON_NO_PRIMARY_KEY)) {
return true;
}
const metadata = options?.tableMetadata;
if (!metadata?.loadedSections?.includes("primaryKey")) return false;
const columns = metadata.primaryKey?.columns || [];
return metadata.primaryKey === null || columns.length === 0;
}

export function isChenDataViewInsertable(dataset: ChenDataViewDataset | null | undefined) {
return isChenDataViewEditable(dataset) && dataset?.fields.some((field) => field.insertable === true) === true;
}
Expand Down
Loading