mirror of https://github.com/nocodb/nocodb
829 changed files with 29619 additions and 15815 deletions
Binary file not shown.
@ -0,0 +1,138 @@
|
||||
<script setup lang="ts"> |
||||
import { ProjectTypes } from 'nocodb-sdk' |
||||
import { isEeUI, useApi, useVModel, useWorkspace } from '#imports' |
||||
|
||||
const props = defineProps<{ |
||||
modelValue: boolean |
||||
}>() |
||||
|
||||
const emit = defineEmits(['update:modelValue']) |
||||
|
||||
const { api } = useApi() |
||||
|
||||
const { sharedBaseId } = useCopySharedBase() |
||||
|
||||
const workspaceStore = useWorkspace() |
||||
|
||||
const { populateWorkspace } = workspaceStore |
||||
|
||||
const { workspacesList } = storeToRefs(workspaceStore) |
||||
|
||||
const { ncNavigateTo } = useGlobal() |
||||
|
||||
const dialogShow = useVModel(props, 'modelValue', emit) |
||||
|
||||
const options = ref({ |
||||
includeData: true, |
||||
includeViews: true, |
||||
}) |
||||
|
||||
const optionsToExclude = computed(() => { |
||||
const { includeData, includeViews } = options.value |
||||
return { |
||||
excludeData: !includeData, |
||||
excludeViews: !includeViews, |
||||
} |
||||
}) |
||||
|
||||
const isLoading = ref(false) |
||||
|
||||
const selectedWorkspace = ref<string>() |
||||
|
||||
const { $e, $poller } = useNuxtApp() |
||||
|
||||
const _duplicate = async () => { |
||||
if (!selectedWorkspace.value && isEeUI) return |
||||
|
||||
try { |
||||
isLoading.value = true |
||||
const jobData = await api.base.duplicateShared(selectedWorkspace.value ?? 'nc', sharedBaseId.value, { |
||||
options: optionsToExclude.value, |
||||
base: isEeUI |
||||
? { |
||||
fk_workspace_id: selectedWorkspace.value, |
||||
type: ProjectTypes.DATABASE, |
||||
} |
||||
: {}, |
||||
}) |
||||
|
||||
sharedBaseId.value = null |
||||
|
||||
$poller.subscribe( |
||||
{ id: jobData.id }, |
||||
async (data: { |
||||
id: string |
||||
status?: string |
||||
data?: { |
||||
error?: { |
||||
message: string |
||||
} |
||||
message?: string |
||||
result?: any |
||||
} |
||||
}) => { |
||||
if (data.status !== 'close') { |
||||
if (data.status === JobStatus.COMPLETED) { |
||||
console.log('job completed', jobData) |
||||
await ncNavigateTo({ |
||||
...(isEeUI ? { workspaceId: jobData.fk_workspace_id } : {}), |
||||
baseId: jobData.base_id, |
||||
}) |
||||
isLoading.value = false |
||||
dialogShow.value = false |
||||
} else if (data.status === JobStatus.FAILED) { |
||||
message.error('Failed to duplicate shared base') |
||||
await populateWorkspace() |
||||
isLoading.value = false |
||||
dialogShow.value = false |
||||
} |
||||
} |
||||
}, |
||||
) |
||||
|
||||
$e('a:base:duplicate-shared-base') |
||||
} catch (e: any) { |
||||
message.error(await extractSdkResponseErrorMsg(e)) |
||||
isLoading.value = false |
||||
dialogShow.value = false |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<template> |
||||
<GeneralModal v-model:visible="dialogShow" class="!w-[30rem]" wrap-class-name="nc-modal-project-duplicate"> |
||||
<div> |
||||
<div class="prose-xl font-bold self-center">{{ $t('general.duplicate') }} {{ $t('labels.sharedBase') }}</div> |
||||
<template v-if="isEeUI"> |
||||
<div class="my-4">Select workspace to duplicate shared base to:</div> |
||||
|
||||
<NcSelect |
||||
v-model:value="selectedWorkspace" |
||||
class="w-full" |
||||
:options="workspacesList.map((w) => ({ label: `${w.title[0].toUpperCase()}${w.title.slice(1)}`, value: w.id }))" |
||||
placeholder="Select Workspace" |
||||
/> |
||||
</template> |
||||
|
||||
<div class="prose-md self-center text-gray-500 mt-4">{{ $t('title.advancedSettings') }}</div> |
||||
|
||||
<a-divider class="!m-0 !p-0 !my-2" /> |
||||
|
||||
<div class="text-xs p-2"> |
||||
<a-checkbox v-model:checked="options.includeData">{{ $t('labels.includeData') }}</a-checkbox> |
||||
<a-checkbox v-model:checked="options.includeViews">{{ $t('labels.includeView') }}</a-checkbox> |
||||
</div> |
||||
</div> |
||||
<div class="flex flex-row gap-x-2 mt-2.5 pt-2.5 justify-end"> |
||||
<NcButton key="back" type="secondary" @click="dialogShow = false">{{ $t('general.cancel') }}</NcButton> |
||||
<NcButton |
||||
key="submit" |
||||
v-e="['a:shared-base:duplicate']" |
||||
:loading="isLoading" |
||||
:disabled="!selectedWorkspace && isEeUI" |
||||
@click="_duplicate" |
||||
>{{ $t('general.confirm') }} |
||||
</NcButton> |
||||
</div> |
||||
</GeneralModal> |
||||
</template> |
@ -0,0 +1,9 @@
|
||||
import { createSharedComposable, ref } from '#imports' |
||||
|
||||
export const useCopySharedBase = createSharedComposable(() => { |
||||
const sharedBaseId = ref<string | null>(null) |
||||
|
||||
return { |
||||
sharedBaseId, |
||||
} |
||||
}) |
@ -1,97 +0,0 @@
|
||||
import type { ColumnType, GridColumnReqType, GridColumnType, ViewType } from 'nocodb-sdk' |
||||
import type { Ref } from 'vue' |
||||
import { IsPublicInj, computed, inject, ref, useMetas, useNuxtApp, useRoles, useUndoRedo, watch } from '#imports' |
||||
|
||||
const [useProvideGridViewColumn, useGridViewColumn] = useInjectionState( |
||||
(view: Ref<(ViewType & { columns?: GridColumnType[] }) | undefined>, statePublic = false) => { |
||||
const { isUIAllowed } = useRoles() |
||||
|
||||
const { $api } = useNuxtApp() |
||||
|
||||
const { metas } = useMetas() |
||||
|
||||
const { addUndo, defineViewScope } = useUndoRedo() |
||||
|
||||
const gridViewCols = ref<Record<string, GridColumnType>>({}) |
||||
const resizingColOldWith = ref('200px') |
||||
const isPublic = inject(IsPublicInj, ref(statePublic)) |
||||
|
||||
const columns = computed<ColumnType[]>(() => metas.value?.[view.value?.fk_model_id as string]?.columns || []) |
||||
|
||||
const loadGridViewColumns = async () => { |
||||
if (!view.value?.id && !isPublic.value) return |
||||
|
||||
const colsData: GridColumnType[] = |
||||
(isPublic.value ? view.value?.columns : await $api.dbView.gridColumnsList(view.value!.id!)) ?? [] |
||||
|
||||
gridViewCols.value = colsData.reduce<Record<string, GridColumnType>>( |
||||
(o, col) => ({ |
||||
...o, |
||||
[col.fk_column_id as string]: col, |
||||
}), |
||||
{}, |
||||
) |
||||
} |
||||
|
||||
/** when columns changes(create/delete) reload grid columns |
||||
* or when view changes reload columns width */ |
||||
watch( |
||||
[() => columns.value?.length, () => view.value?.id], |
||||
async (n) => { |
||||
if (n[1]) await loadGridViewColumns() |
||||
}, |
||||
{ immediate: true }, |
||||
) |
||||
|
||||
const updateGridViewColumn = async (id: string, props: Partial<GridColumnReqType>, undo = false) => { |
||||
if (!undo) { |
||||
const oldProps = Object.keys(props).reduce<Partial<GridColumnReqType>>((o: any, k) => { |
||||
if (gridViewCols.value[id][k as keyof GridColumnType]) { |
||||
if (k === 'width') o[k] = `${resizingColOldWith.value}px` |
||||
else o[k] = gridViewCols.value[id][k as keyof GridColumnType] |
||||
} |
||||
return o |
||||
}, {}) |
||||
addUndo({ |
||||
redo: { |
||||
fn: (w: Partial<GridColumnReqType>) => updateGridViewColumn(id, w, true), |
||||
args: [props], |
||||
}, |
||||
undo: { |
||||
fn: (w: Partial<GridColumnReqType>) => updateGridViewColumn(id, w, true), |
||||
args: [oldProps], |
||||
}, |
||||
scope: defineViewScope({ view: view.value }), |
||||
}) |
||||
} |
||||
|
||||
// sync with server if allowed
|
||||
if (!isPublic.value && isUIAllowed('viewFieldEdit') && gridViewCols.value[id]?.id) { |
||||
await $api.dbView.gridColumnUpdate(gridViewCols.value[id].id as string, { |
||||
...props, |
||||
}) |
||||
} |
||||
|
||||
if (gridViewCols.value?.[id]) { |
||||
Object.assign(gridViewCols.value[id], { |
||||
...gridViewCols.value[id], |
||||
...props, |
||||
}) |
||||
} else { |
||||
// fallback to reload
|
||||
await loadGridViewColumns() |
||||
} |
||||
} |
||||
|
||||
return { loadGridViewColumns, updateGridViewColumn, gridViewCols, resizingColOldWith } |
||||
}, |
||||
'useGridViewColumn', |
||||
) |
||||
|
||||
export { useProvideGridViewColumn } |
||||
|
||||
export function useGridViewColumnOrThrow() { |
||||
const gridViewColumn = useGridViewColumn() |
||||
if (gridViewColumn == null) throw new Error('Please call `useProvideGridViewColumn` on the appropriate parent component') |
||||
return gridViewColumn |
||||
} |
@ -1,296 +1,363 @@
|
||||
import { ViewTypes, isSystemColumn } from 'nocodb-sdk' |
||||
import type { ColumnType, MapType, TableType, ViewType } from 'nocodb-sdk' |
||||
import type { ColumnType, GridColumnReqType, GridColumnType, MapType, TableType, ViewType } from 'nocodb-sdk' |
||||
import type { ComputedRef, Ref } from 'vue' |
||||
import { IsPublicInj, computed, inject, ref, storeToRefs, useBase, useNuxtApp, useRoles, useUndoRedo, watch } from '#imports' |
||||
import { computed, ref, storeToRefs, useBase, useNuxtApp, useRoles, useUndoRedo, watch } from '#imports' |
||||
import type { Field } from '#imports' |
||||
|
||||
export function useViewColumns( |
||||
view: Ref<ViewType | undefined>, |
||||
meta: Ref<TableType | undefined> | ComputedRef<TableType | undefined>, |
||||
reloadData?: () => void, |
||||
) { |
||||
const isPublic = inject(IsPublicInj, ref(false)) |
||||
const [useProvideViewColumns, useViewColumns] = useInjectionState( |
||||
( |
||||
view: Ref<ViewType | undefined>, |
||||
meta: Ref<TableType | undefined> | ComputedRef<TableType | undefined>, |
||||
reloadData?: () => void, |
||||
isPublic = false, |
||||
) => { |
||||
const fields = ref<Field[]>() |
||||
|
||||
const fields = ref<Field[]>() |
||||
const filterQuery = ref('') |
||||
|
||||
const filterQuery = ref('') |
||||
const { $api, $e } = useNuxtApp() |
||||
|
||||
const { $api, $e } = useNuxtApp() |
||||
const { isUIAllowed } = useRoles() |
||||
|
||||
const { isUIAllowed } = useRoles() |
||||
const { isSharedBase } = storeToRefs(useBase()) |
||||
|
||||
const { isSharedBase } = storeToRefs(useBase()) |
||||
const isViewColumnsLoading = ref(false) |
||||
|
||||
const isViewColumnsLoading = ref(false) |
||||
const { addUndo, defineViewScope } = useUndoRedo() |
||||
|
||||
const { addUndo, defineViewScope } = useUndoRedo() |
||||
const isLocalMode = computed( |
||||
() => isPublic || !isUIAllowed('viewFieldEdit') || !isUIAllowed('viewFieldEdit') || isSharedBase.value, |
||||
) |
||||
|
||||
const isLocalMode = computed( |
||||
() => isPublic.value || !isUIAllowed('viewFieldEdit') || !isUIAllowed('viewFieldEdit') || isSharedBase.value, |
||||
) |
||||
const localChanges = ref<Field[]>([]) |
||||
|
||||
const localChanges = ref<Field[]>([]) |
||||
const isColumnViewEssential = (column: ColumnType) => { |
||||
// TODO: consider at some point ti delegate this via a cleaner design pattern to view specific check logic
|
||||
// which could be inside of a view specific helper class (and generalized via an interface)
|
||||
// (on the other hand, the logic complexity is still very low atm - might be overkill)
|
||||
return view.value?.type === ViewTypes.MAP && (view.value?.view as MapType)?.fk_geo_data_col_id === column.id |
||||
} |
||||
|
||||
const isColumnViewEssential = (column: ColumnType) => { |
||||
// TODO: consider at some point ti delegate this via a cleaner design pattern to view specific check logic
|
||||
// which could be inside of a view specific helper class (and generalized via an interface)
|
||||
// (on the other hand, the logic complexity is still very low atm - might be overkill)
|
||||
return view.value?.type === ViewTypes.MAP && (view.value?.view as MapType)?.fk_geo_data_col_id === column.id |
||||
} |
||||
const metaColumnById = computed<Record<string, ColumnType>>(() => { |
||||
if (!meta.value?.columns) return {} |
||||
|
||||
const metaColumnById = computed<Record<string, ColumnType>>(() => { |
||||
if (!meta.value?.columns) return {} |
||||
return (meta.value.columns as ColumnType[]).reduce( |
||||
(acc, curr) => ({ |
||||
...acc, |
||||
[curr.id!]: curr, |
||||
}), |
||||
{}, |
||||
) as Record<string, ColumnType> |
||||
}) |
||||
|
||||
return (meta.value.columns as ColumnType[]).reduce( |
||||
(acc, curr) => ({ |
||||
...acc, |
||||
[curr.id!]: curr, |
||||
}), |
||||
{}, |
||||
) as Record<string, ColumnType> |
||||
}) |
||||
const gridViewCols = ref<Record<string, GridColumnType>>({}) |
||||
|
||||
const loadViewColumns = async () => { |
||||
if (!meta || !view) return |
||||
const loadViewColumns = async () => { |
||||
if (!meta || !view) return |
||||
|
||||
let order = 1 |
||||
let order = 1 |
||||
|
||||
if (view.value?.id) { |
||||
const data = (isPublic.value ? meta.value?.columns : (await $api.dbViewColumn.list(view.value.id)).list) as any[] |
||||
if (view.value?.id) { |
||||
const data = (isPublic ? meta.value?.columns : (await $api.dbViewColumn.list(view.value.id)).list) as any[] |
||||
|
||||
const fieldById = data.reduce<Record<string, any>>((acc, curr) => { |
||||
curr.show = !!curr.show |
||||
|
||||
return { |
||||
...acc, |
||||
[curr.fk_column_id]: curr, |
||||
} |
||||
}, {}) |
||||
|
||||
fields.value = meta.value?.columns |
||||
?.map((column: ColumnType) => { |
||||
const currentColumnField = fieldById[column.id!] || {} |
||||
const fieldById = data.reduce<Record<string, any>>((acc, curr) => { |
||||
curr.show = !!curr.show |
||||
|
||||
return { |
||||
title: column.title, |
||||
fk_column_id: column.id, |
||||
...currentColumnField, |
||||
show: currentColumnField.show || isColumnViewEssential(currentColumnField), |
||||
order: currentColumnField.order || order++, |
||||
system: isSystemColumn(metaColumnById?.value?.[currentColumnField.fk_column_id!]), |
||||
isViewEssentialField: isColumnViewEssential(column), |
||||
...acc, |
||||
[curr.fk_column_id]: curr, |
||||
} |
||||
}) |
||||
.sort((a: Field, b: Field) => a.order - b.order) |
||||
|
||||
if (isLocalMode.value && fields.value) { |
||||
for (const field of localChanges.value) { |
||||
const fieldIndex = fields.value.findIndex((f) => f.fk_column_id === field.fk_column_id) |
||||
if (fieldIndex !== undefined && fieldIndex > -1) { |
||||
fields.value[fieldIndex] = field |
||||
fields.value = fields.value.sort((a: Field, b: Field) => a.order - b.order) |
||||
}, {}) |
||||
|
||||
fields.value = meta.value?.columns |
||||
?.map((column: ColumnType) => { |
||||
const currentColumnField = fieldById[column.id!] || {} |
||||
|
||||
return { |
||||
title: column.title, |
||||
fk_column_id: column.id, |
||||
...currentColumnField, |
||||
show: currentColumnField.show || isColumnViewEssential(currentColumnField), |
||||
order: currentColumnField.order || order++, |
||||
system: isSystemColumn(metaColumnById?.value?.[currentColumnField.fk_column_id!]), |
||||
isViewEssentialField: isColumnViewEssential(column), |
||||
} |
||||
}) |
||||
.sort((a: Field, b: Field) => a.order - b.order) |
||||
|
||||
if (isLocalMode.value && fields.value) { |
||||
for (const field of localChanges.value) { |
||||
const fieldIndex = fields.value.findIndex((f) => f.fk_column_id === field.fk_column_id) |
||||
if (fieldIndex !== undefined && fieldIndex > -1) { |
||||
fields.value[fieldIndex] = field |
||||
fields.value = fields.value.sort((a: Field, b: Field) => a.order - b.order) |
||||
} |
||||
} |
||||
} |
||||
|
||||
const colsData: GridColumnType[] = (isPublic.value ? view.value?.columns : fields.value) ?? [] |
||||
|
||||
gridViewCols.value = colsData.reduce<Record<string, GridColumnType>>( |
||||
(o, col) => ({ |
||||
...o, |
||||
[col.fk_column_id as string]: col, |
||||
}), |
||||
{}, |
||||
) |
||||
} |
||||
} |
||||
} |
||||
|
||||
const showAll = async (ignoreIds?: any) => { |
||||
if (isLocalMode.value) { |
||||
fields.value = fields.value?.map((field: Field) => ({ |
||||
...field, |
||||
show: true, |
||||
})) |
||||
reloadData?.() |
||||
return |
||||
} |
||||
|
||||
if (view?.value?.id) { |
||||
if (ignoreIds) { |
||||
await $api.dbView.showAllColumn(view.value.id, { |
||||
ignoreIds, |
||||
}) |
||||
} else { |
||||
await $api.dbView.showAllColumn(view.value.id) |
||||
const showAll = async (ignoreIds?: any) => { |
||||
if (isLocalMode.value) { |
||||
fields.value = fields.value?.map((field: Field) => ({ |
||||
...field, |
||||
show: true, |
||||
})) |
||||
reloadData?.() |
||||
return |
||||
} |
||||
|
||||
if (view?.value?.id) { |
||||
if (ignoreIds) { |
||||
await $api.dbView.showAllColumn(view.value.id, { |
||||
ignoreIds, |
||||
}) |
||||
} else { |
||||
await $api.dbView.showAllColumn(view.value.id) |
||||
} |
||||
} |
||||
|
||||
await loadViewColumns() |
||||
reloadData?.() |
||||
$e('a:fields:show-all') |
||||
} |
||||
const hideAll = async (ignoreIds?: any) => { |
||||
if (isLocalMode.value) { |
||||
fields.value = fields.value?.map((field: Field) => ({ |
||||
...field, |
||||
show: !!field.isViewEssentialField, |
||||
})) |
||||
reloadData?.() |
||||
return |
||||
} |
||||
if (view?.value?.id) { |
||||
if (ignoreIds) { |
||||
await $api.dbView.hideAllColumn(view.value.id, { |
||||
ignoreIds, |
||||
}) |
||||
} else { |
||||
await $api.dbView.hideAllColumn(view.value.id) |
||||
} |
||||
} |
||||
|
||||
await loadViewColumns() |
||||
reloadData?.() |
||||
$e('a:fields:show-all') |
||||
} |
||||
const hideAll = async (ignoreIds?: any) => { |
||||
if (isLocalMode.value) { |
||||
fields.value = fields.value?.map((field: Field) => ({ |
||||
...field, |
||||
show: !!field.isViewEssentialField, |
||||
})) |
||||
await loadViewColumns() |
||||
reloadData?.() |
||||
return |
||||
$e('a:fields:show-all') |
||||
} |
||||
if (view?.value?.id) { |
||||
if (ignoreIds) { |
||||
await $api.dbView.hideAllColumn(view.value.id, { |
||||
ignoreIds, |
||||
|
||||
const saveOrUpdate = async (field: any, index: number) => { |
||||
if (isLocalMode.value && fields.value) { |
||||
fields.value[index] = field |
||||
meta.value!.columns = meta.value!.columns?.map((column: ColumnType) => { |
||||
if (column.id === field.fk_column_id) { |
||||
return { |
||||
...column, |
||||
...field, |
||||
id: field.fk_column_id, |
||||
} |
||||
} |
||||
return column |
||||
}) |
||||
} else { |
||||
await $api.dbView.hideAllColumn(view.value.id) |
||||
|
||||
localChanges.value.push(field) |
||||
} |
||||
} |
||||
|
||||
await loadViewColumns() |
||||
reloadData?.() |
||||
$e('a:fields:show-all') |
||||
} |
||||
if (isUIAllowed('viewFieldEdit')) { |
||||
if (field.id && view?.value?.id) { |
||||
await $api.dbViewColumn.update(view.value.id, field.id, field) |
||||
} else if (view.value?.id) { |
||||
const insertedField = (await $api.dbViewColumn.create(view.value.id, field)) as any |
||||
|
||||
const saveOrUpdate = async (field: any, index: number) => { |
||||
if (isLocalMode.value && fields.value) { |
||||
fields.value[index] = field |
||||
meta.value!.columns = meta.value!.columns?.map((column: ColumnType) => { |
||||
if (column.id === field.fk_column_id) { |
||||
return { |
||||
...column, |
||||
...field, |
||||
id: field.fk_column_id, |
||||
} |
||||
/** update the field in fields if defined */ |
||||
if (fields.value) fields.value[index] = insertedField |
||||
|
||||
return insertedField |
||||
} |
||||
return column |
||||
}) |
||||
} |
||||
|
||||
localChanges.value.push(field) |
||||
await loadViewColumns() |
||||
reloadData?.() |
||||
} |
||||
|
||||
if (isUIAllowed('viewFieldEdit')) { |
||||
if (field.id && view?.value?.id) { |
||||
await $api.dbViewColumn.update(view.value.id, field.id, field) |
||||
} else if (view.value?.id) { |
||||
const insertedField = (await $api.dbViewColumn.create(view.value.id, field)) as any |
||||
const showSystemFields = computed({ |
||||
get() { |
||||
return (view.value?.show_system_fields as boolean) || false |
||||
}, |
||||
set(v: boolean) { |
||||
if (view?.value?.id) { |
||||
if (!isLocalMode.value) { |
||||
$api.dbView |
||||
.update(view.value.id, { |
||||
show_system_fields: v, |
||||
}) |
||||
.finally(() => { |
||||
loadViewColumns() |
||||
reloadData?.() |
||||
}) |
||||
} |
||||
view.value.show_system_fields = v |
||||
} |
||||
$e('a:fields:system-fields') |
||||
}, |
||||
}) |
||||
|
||||
/** update the field in fields if defined */ |
||||
if (fields.value) fields.value[index] = insertedField |
||||
const filteredFieldList = computed(() => { |
||||
return ( |
||||
fields.value?.filter((field: Field) => { |
||||
if (metaColumnById?.value?.[field.fk_column_id!]?.pv) return true |
||||
|
||||
return insertedField |
||||
} |
||||
} |
||||
// hide system columns if not enabled
|
||||
if (!showSystemFields.value && isSystemColumn(metaColumnById?.value?.[field.fk_column_id!])) { |
||||
return false |
||||
} |
||||
|
||||
await loadViewColumns() |
||||
reloadData?.() |
||||
} |
||||
if (filterQuery.value === '') { |
||||
return true |
||||
} else { |
||||
return field.title.toLowerCase().includes(filterQuery.value.toLowerCase()) |
||||
} |
||||
}) || [] |
||||
) |
||||
}) |
||||
|
||||
const showSystemFields = computed({ |
||||
get() { |
||||
return (view.value?.show_system_fields as boolean) || false |
||||
}, |
||||
set(v: boolean) { |
||||
if (view?.value?.id) { |
||||
if (!isLocalMode.value) { |
||||
$api.dbView |
||||
.update(view.value.id, { |
||||
show_system_fields: v, |
||||
}) |
||||
.finally(() => { |
||||
loadViewColumns() |
||||
reloadData?.() |
||||
}) |
||||
} |
||||
view.value.show_system_fields = v |
||||
} |
||||
$e('a:fields:system-fields') |
||||
}, |
||||
}) |
||||
|
||||
const filteredFieldList = computed(() => { |
||||
return ( |
||||
fields.value?.filter((field: Field) => { |
||||
if (metaColumnById?.value?.[field.fk_column_id!]?.pv) return true |
||||
|
||||
// hide system columns if not enabled
|
||||
if (!showSystemFields.value && isSystemColumn(metaColumnById?.value?.[field.fk_column_id!])) { |
||||
return false |
||||
} |
||||
const sortedAndFilteredFields = computed<ColumnType[]>(() => { |
||||
return (fields?.value |
||||
?.filter((field: Field) => { |
||||
// hide system columns if not enabled
|
||||
if ( |
||||
!showSystemFields.value && |
||||
metaColumnById.value && |
||||
metaColumnById?.value?.[field.fk_column_id!] && |
||||
isSystemColumn(metaColumnById.value?.[field.fk_column_id!]) && |
||||
!metaColumnById.value?.[field.fk_column_id!]?.pv |
||||
) { |
||||
return false |
||||
} |
||||
return field.show && metaColumnById?.value?.[field.fk_column_id!] |
||||
}) |
||||
?.sort((a: Field, b: Field) => a.order - b.order) |
||||
?.map((field: Field) => metaColumnById?.value?.[field.fk_column_id!]) || []) as ColumnType[] |
||||
}) |
||||
|
||||
if (filterQuery.value === '') { |
||||
return true |
||||
} else { |
||||
return field.title.toLowerCase().includes(filterQuery.value.toLowerCase()) |
||||
} |
||||
}) || [] |
||||
) |
||||
}) |
||||
|
||||
const sortedAndFilteredFields = computed<ColumnType[]>(() => { |
||||
return (fields?.value |
||||
?.filter((field: Field) => { |
||||
// hide system columns if not enabled
|
||||
if ( |
||||
!showSystemFields.value && |
||||
metaColumnById.value && |
||||
metaColumnById?.value?.[field.fk_column_id!] && |
||||
isSystemColumn(metaColumnById.value?.[field.fk_column_id!]) && |
||||
!metaColumnById.value?.[field.fk_column_id!]?.pv |
||||
) { |
||||
return false |
||||
} |
||||
return field.show && metaColumnById?.value?.[field.fk_column_id!] |
||||
}) |
||||
?.sort((a: Field, b: Field) => a.order - b.order) |
||||
?.map((field: Field) => metaColumnById?.value?.[field.fk_column_id!]) || []) as ColumnType[] |
||||
}) |
||||
|
||||
const toggleFieldVisibility = (checked: boolean, field: any) => { |
||||
const fieldIndex = fields.value?.findIndex((f) => f.fk_column_id === field.fk_column_id) |
||||
if (!fieldIndex && fieldIndex !== 0) return |
||||
addUndo({ |
||||
undo: { |
||||
fn: (v: boolean) => { |
||||
field.show = !v |
||||
saveOrUpdate(field, fieldIndex) |
||||
const toggleFieldVisibility = (checked: boolean, field: any) => { |
||||
const fieldIndex = fields.value?.findIndex((f) => f.fk_column_id === field.fk_column_id) |
||||
if (!fieldIndex && fieldIndex !== 0) return |
||||
addUndo({ |
||||
undo: { |
||||
fn: (v: boolean) => { |
||||
field.show = !v |
||||
saveOrUpdate(field, fieldIndex) |
||||
}, |
||||
args: [checked], |
||||
}, |
||||
args: [checked], |
||||
}, |
||||
redo: { |
||||
fn: (v: boolean) => { |
||||
field.show = v |
||||
saveOrUpdate(field, fieldIndex) |
||||
redo: { |
||||
fn: (v: boolean) => { |
||||
field.show = v |
||||
saveOrUpdate(field, fieldIndex) |
||||
}, |
||||
args: [checked], |
||||
}, |
||||
args: [checked], |
||||
}, |
||||
scope: defineViewScope({ view: view.value }), |
||||
}) |
||||
saveOrUpdate(field, fieldIndex) |
||||
} |
||||
|
||||
// reload view columns when active view changes
|
||||
// or when columns count changes(delete/add)
|
||||
watch( |
||||
[() => view?.value?.id, () => meta.value?.columns?.length], |
||||
async ([newViewId]) => { |
||||
// reload only if view belongs to current table
|
||||
if (newViewId && view.value?.fk_model_id === meta.value?.id) { |
||||
isViewColumnsLoading.value = true |
||||
try { |
||||
await loadViewColumns() |
||||
} catch (e) { |
||||
console.error(e) |
||||
scope: defineViewScope({ view: view.value }), |
||||
}) |
||||
saveOrUpdate(field, fieldIndex) |
||||
} |
||||
|
||||
// reload view columns when active view changes
|
||||
// or when columns count changes(delete/add)
|
||||
watch( |
||||
[() => view?.value?.id, () => meta.value?.columns?.length], |
||||
async ([newViewId]) => { |
||||
// reload only if view belongs to current table
|
||||
if (newViewId && view.value?.fk_model_id === meta.value?.id) { |
||||
isViewColumnsLoading.value = true |
||||
try { |
||||
await loadViewColumns() |
||||
} catch (e) { |
||||
console.error(e) |
||||
} |
||||
isViewColumnsLoading.value = false |
||||
} |
||||
isViewColumnsLoading.value = false |
||||
}, |
||||
{ immediate: true }, |
||||
) |
||||
|
||||
const resizingColOldWith = ref('200px') |
||||
|
||||
const updateGridViewColumn = async (id: string, props: Partial<GridColumnReqType>, undo = false) => { |
||||
if (!undo) { |
||||
const oldProps = Object.keys(props).reduce<Partial<GridColumnReqType>>((o: any, k) => { |
||||
if (gridViewCols.value[id][k as keyof GridColumnType]) { |
||||
if (k === 'width') o[k] = `${resizingColOldWith.value}px` |
||||
else o[k] = gridViewCols.value[id][k as keyof GridColumnType] |
||||
} |
||||
return o |
||||
}, {}) |
||||
addUndo({ |
||||
redo: { |
||||
fn: (w: Partial<GridColumnReqType>) => updateGridViewColumn(id, w, true), |
||||
args: [props], |
||||
}, |
||||
undo: { |
||||
fn: (w: Partial<GridColumnReqType>) => updateGridViewColumn(id, w, true), |
||||
args: [oldProps], |
||||
}, |
||||
scope: defineViewScope({ view: view.value }), |
||||
}) |
||||
} |
||||
|
||||
// sync with server if allowed
|
||||
if (!isPublic.value && isUIAllowed('viewFieldEdit') && gridViewCols.value[id]?.id) { |
||||
await $api.dbView.gridColumnUpdate(gridViewCols.value[id].id as string, { |
||||
...props, |
||||
}) |
||||
} |
||||
|
||||
if (gridViewCols.value?.[id]) { |
||||
Object.assign(gridViewCols.value[id], { |
||||
...gridViewCols.value[id], |
||||
...props, |
||||
}) |
||||
} else { |
||||
// fallback to reload
|
||||
await loadViewColumns() |
||||
} |
||||
}, |
||||
{ immediate: true }, |
||||
) |
||||
|
||||
return { |
||||
fields, |
||||
loadViewColumns, |
||||
filteredFieldList, |
||||
filterQuery, |
||||
showAll, |
||||
hideAll, |
||||
saveOrUpdate, |
||||
sortedAndFilteredFields, |
||||
showSystemFields, |
||||
metaColumnById, |
||||
toggleFieldVisibility, |
||||
isViewColumnsLoading, |
||||
} |
||||
} |
||||
|
||||
return { |
||||
fields, |
||||
loadViewColumns, |
||||
filteredFieldList, |
||||
filterQuery, |
||||
showAll, |
||||
hideAll, |
||||
saveOrUpdate, |
||||
sortedAndFilteredFields, |
||||
showSystemFields, |
||||
metaColumnById, |
||||
toggleFieldVisibility, |
||||
isViewColumnsLoading, |
||||
updateGridViewColumn, |
||||
gridViewCols, |
||||
resizingColOldWith, |
||||
} |
||||
}, |
||||
'useViewColumnsOrThrow', |
||||
) |
||||
|
||||
export { useProvideViewColumns } |
||||
|
||||
export function useViewColumnsOrThrow() { |
||||
const viewColumns = useViewColumns() |
||||
if (viewColumns == null) throw new Error('Please call `useProvideViewColumns` on the appropriate parent component') |
||||
return viewColumns |
||||
} |
||||
|
Before Width: | Height: | Size: 24 KiB |
@ -0,0 +1,21 @@
|
||||
<script lang="ts" setup> |
||||
import { useBase, useCopySharedBase, useRoute } from '#imports' |
||||
|
||||
const route = useRoute() |
||||
|
||||
const { sharedBaseId } = useCopySharedBase() |
||||
|
||||
const { forcedProjectId } = storeToRefs(useBase()) |
||||
|
||||
onMounted(() => { |
||||
sharedBaseId.value = route.query.base as string |
||||
if (forcedProjectId?.value) forcedProjectId.value = undefined |
||||
navigateTo(`/`) |
||||
}) |
||||
</script> |
||||
|
||||
<template> |
||||
<div></div> |
||||
</template> |
||||
|
||||
<style scoped></style> |
@ -1,67 +0,0 @@
|
||||
--- |
||||
title: 'Environment Variables' |
||||
description: 'Environment Variables for NocoDB!' |
||||
hide_table_of_contents: true |
||||
--- |
||||
|
||||
For production usecases, it is **recommended** to configure |
||||
- `NC_DB`, |
||||
- `NC_AUTH_JWT_SECRET`, |
||||
- `NC_PUBLIC_URL`, |
||||
- `NC_REDIS_URL` |
||||
|
||||
| Variable | Comments | If absent | |
||||
|---|---|---| |
||||
| NC_DB | See our example database URLs [here](https://github.com/nocodb/nocodb#docker). | A local SQLite will be created in root folder if `NC_DB` is not provided | |
||||
| NC_DB_JSON | Can be used instead of `NC_DB` and value should be valid knex connection JSON | | |
||||
| NC_DB_JSON_FILE | Can be used instead of `NC_DB` and value should be a valid path to knex connection JSON | | |
||||
| DATABASE_URL | JDBC URL Format. Can be used instead of NC_DB. | | |
||||
| DATABASE_URL_FILE | Can be used instead of DATABASE_URL: path to file containing JDBC URL Format. | | |
||||
| NC_AUTH_JWT_SECRET | JWT secret used for auth and storing other secrets | A random secret will be generated | |
||||
| PORT | For setting app running port | `8080` | |
||||
| DB_QUERY_LIMIT_DEFAULT | Default pagination limit | 25 | |
||||
| DB_QUERY_LIMIT_MAX | Maximum allowed pagination limit | 1000 | |
||||
| DB_QUERY_LIMIT_MIN | Minimum allowed pagination limit | 1 | |
||||
| NC_TOOL_DIR | App directory to keep metadata and app related files | Defaults to current working directory. In docker maps to `/usr/app/data/` for mounting volume. | |
||||
| NC_PUBLIC_URL | Used for sending Email invitations | Best guess from http request params | |
||||
| NC_JWT_EXPIRES_IN | JWT token expiry time | `10h` | |
||||
| NC_CONNECT_TO_EXTERNAL_DB_DISABLED | Disable Project creation with external database | | |
||||
| NC_INVITE_ONLY_SIGNUP | Removed since version 0.99.0 and now it's recommended to use [super admin settings menu](/setup-and-usages/account-settings#enable--disable-signup). Allow users to signup only via invite url, value should be any non-empty string. | | |
||||
| NUXT_PUBLIC_NC_BACKEND_URL | Custom Backend URL | ``http://localhost:8080`` will be used | |
||||
| NC_REQUEST_BODY_SIZE | Request body size [limit](https://expressjs.com/en/resources/middleware/body-parser.html#limit) | `1048576` | |
||||
| NC_EXPORT_MAX_TIMEOUT | After NC_EXPORT_MAX_TIMEOUT csv gets downloaded in batches | Default value 5000(in millisecond) will be used | |
||||
| NC_DISABLE_TELE | Disable telemetry | | |
||||
| NC_DASHBOARD_URL | Custom dashboard url path | `/dashboard` | |
||||
| NC_GOOGLE_CLIENT_ID | Google client id to enable google authentication | | |
||||
| NC_GOOGLE_CLIENT_SECRET | Google client secret to enable google authentication | | |
||||
| NC_MIGRATIONS_DISABLED | Disable NocoDB migration | | |
||||
| NC_MIN | If set to any non-empty string the default splash screen(initial welcome animation) and matrix screensaver will disable | | |
||||
| NC_SENTRY_DSN | For Sentry monitoring | | |
||||
| NC_REDIS_URL | Custom Redis URL. Example: `redis://:authpassword@127.0.0.1:6380/4` | Meta data will be stored in memory | |
||||
| NC_DISABLE_ERR_REPORT | Disable error reporting | | |
||||
| NC_DISABLE_CACHE | To be used only while debugging. On setting this to `true` - meta data be fetched from db instead of redis/cache. | `false` | |
||||
| AWS_ACCESS_KEY_ID | For Litestream - S3 access key id | If Litestream is configured and `NC_DB` is not present. SQLite gets backed up to S3 | |
||||
| AWS_SECRET_ACCESS_KEY | For Litestream - S3 secret access key | If Litestream is configured and `NC_DB` is not present. SQLite gets backed up to S3 | |
||||
| AWS_BUCKET | For Litestream - S3 bucket | If Litestream is configured and `NC_DB` is not present. SQLite gets backed up to S3 | |
||||
| AWS_BUCKET_PATH | For Litestream - S3 bucket path (like folder within S3 bucket) | If Litestream is configured and `NC_DB` is not present. SQLite gets backed up to S3 | |
||||
| NC_SMTP_FROM | For SMTP plugin - Email sender address | | |
||||
| NC_SMTP_HOST | For SMTP plugin - SMTP host value | | |
||||
| NC_SMTP_PORT | For SMTP plugin - SMTP port value | | |
||||
| NC_SMTP_USERNAME | For SMTP plugin (Optional) - SMTP username value for authentication | | |
||||
| NC_SMTP_PASSWORD | For SMTP plugin (Optional) - SMTP password value for authentication | | |
||||
| NC_SMTP_SECURE | For SMTP plugin (Optional) - To enable secure set value as `true` any other value treated as false | | |
||||
| NC_SMTP_IGNORE_TLS | For SMTP plugin (Optional) - To ignore tls set value as `true` any other value treated as false. For more info visit https://nodemailer.com/smtp/ | | |
||||
| NC_S3_BUCKET_NAME | For S3 storage plugin - AWS S3 bucket name | | |
||||
| NC_S3_REGION | For S3 storage plugin - AWS S3 region | | |
||||
| NC_S3_ACCESS_KEY | For S3 storage plugin - AWS access key credential for accessing resource | | |
||||
| NC_S3_ACCESS_SECRET | For S3 storage plugin - AWS access secret credential for accessing resource | | |
||||
| NC_ADMIN_EMAIL | For updating/creating super admin with provided email and password | | |
||||
| NC_ATTACHMENT_FIELD_SIZE | For setting the attachment field size(in Bytes) | Defaults to 20MB | |
||||
| NC_ADMIN_PASSWORD | For updating/creating super admin with provided email and password. Your password should have at least 8 letters with one uppercase, one number and one special letter(Allowed special chars $&+,:;=?@#\|'.^*()%!_-" ) | | |
||||
| NODE_OPTIONS | For passing Node.js [options](https://nodejs.org/api/cli.html#node_optionsoptions) to instance | | |
||||
| NC_MINIMAL_DBS | Create a new SQLite file for each project. All the db files are stored in `nc_minimal_dbs` folder in current working directory. (This option restricts project creation on external sources) | | |
||||
| NC_DISABLE_AUDIT | Disable Audit Log | `false` | |
||||
| NC_AUTOMATION_LOG_LEVEL | Possible Values: `OFF`, `ERROR`, `ALL`. See [Webhooks](/developer-resources/webhooks#call-log) for details. | `OFF` | |
||||
| NC_SECURE_ATTACHMENTS | Allow accessing attachments only through presigned urls. To enable set value as `true` any other value treated as false. (⚠ this will make existing links inaccessible ⚠) | `false` | |
||||
| NC_ATTACHMENT_EXPIRE_SECONDS | How many seconds before expiring presigned attachment urls. (Attachments will expire in at least set seconds and at most 10mins after set time) | 7200 (2 hours) | |
||||
| NC_ALLOW_LOCAL_HOOKS | To enable set value as `true` any other value treated as false. (⚠ this will allow webhooks to call local links which can raise security issues ⚠) | `false` | |
@ -0,0 +1,83 @@
|
||||
--- |
||||
title: 'Quick start' |
||||
keywords: ['NocoDB', 'quick start', 'getting started'] |
||||
--- |
||||
|
||||
|
||||
NocoDB offers you the flexibility of two distinct variants: self-hosted and SaaS (cloud-hosted). In this section, we'll walk you through the initial steps to embark on your NocoDB journey, whether you choose to set it up on your own infrastructure or opt for the convenience of our cloud-hosted service. Let's dive in and unlock the potential of NocoDB for your data management needs. |
||||
|
||||
:::tip |
||||
For this introductory guide, we suggest utilizing the hosted (SaaS) option. New users can take advantage of a complimentary trial period to explore the platform's features. |
||||
::: |
||||
|
||||
## Self Hosted |
||||
|
||||
When you opt for self-hosting, you gain the advantage of running an application on a server that you have direct control over. This grants you the flexibility to choose whether to host the database on your premises or within a server leased from a data center. In this self-administered arrangement, typically found on-premises, you assume full responsibility for the management and upkeep of your server. This level of control ensures that you have complete authority over all aspects of your data and services, eliminating any reliance on third-party service providers. This option is ideal for organizations that require a high degree of control over their data and services, but it does necessitate a higher level of technical expertise. |
||||
|
||||
Setting up NocoDB on your own server is a straightforward process & the articles below will guide you through the steps to get started. |
||||
|
||||
- [Installation](/getting-started/self-hosted/installation) |
||||
- [Environment Variables](/getting-started/self-hosted/environment-variables) |
||||
- [Upgrading](/getting-started/self-hosted/upgrading) |
||||
|
||||
|
||||
## SaaS (Cloud Hosted) |
||||
|
||||
|
||||
### Sign up for a NocoDB account |
||||
|
||||
To get started with NocoDB's cloud-hosted service, follow these steps to sign up for an account: |
||||
|
||||
1. Visit the [NocoDB website](https://www.nocodb.com). |
||||
2. Click on the "Start For Free" button located in the top right corner. |
||||
3. `Sign Up` using Google account. Alternatively, you can also sign up using your email address. |
||||
4. Check your email for a verification link and follow the instructions to verify your account. |
||||
|
||||
Once you've successfully signed up, you will land on the NocoDB dashboard with a default workspace created for you. |
||||
|
||||
### Create another workspace |
||||
|
||||
After signing up and logging in to your NocoDB account, a default workspace is automatically created for you. You can use this workspace or [create a new one](/workspaces/create-workspace) |
||||
|
||||
Your new workspace is now ready, and you can start building your base within it. |
||||
|
||||
### Build a Base |
||||
|
||||
Building a base in NocoDB is where you define the structure of your database, create tables to store your data, add fields to those tables, and establish relationships between tables using Links. This relational approach helps you organize and manage your data effectively, making it easier to work with complex datasets and build powerful applications. Add a [new Base](/bases/create-base). Alternatively, you can also [import existing base from Airtable](/bases/import-base-from-airtable) as a NocoDB project in minutes. |
||||
|
||||
#### Create Tables |
||||
|
||||
Tables are where you store your data like a spreadsheet grid, with data arranged in rows & columns. Once the base is created, you can start [adding new tables](/tables/create-table) to it. You can also [import existing structure data from a CSV, Excel, or JSON file](/tables/create-table-via-import) to populate your tables. |
||||
|
||||
#### Add Fields |
||||
|
||||
Within each table, [define the fields](/fields/fields-overview) that will hold your data. Fields are columnar data containers that hold a specific type of data. Fields can represent various types of information, such as text, numbers, dates, and more. You can find complete list of supported field types [here](/fields/fields-overview). |
||||
|
||||
Use multi-fields editor to manage fields in bulk quickly - add fields, edit them, reorder, change visibility, reconfigure - all from one single window. [Read more](/fields/multi-fields-editor). |
||||
|
||||
#### Establish Relationships with Links |
||||
|
||||
One of NocoDB's powerful features is the ability to establish relationships between tables using [Links](/fields/field-types/links-based/links). Links enable you to connect related data across tables. For example, you can link "Tasks" to a specific "Project" by creating a Link field in the "Projects" table that points to the "Tasks" table. |
||||
|
||||
#### Add Records |
||||
|
||||
Once you have created tables and defined the necessary fields, it's time to start adding records to your base tables. Records are individual entries or rows within your tables, and they contain the actual data you want to store and manage. You can [add records manually](/records/create-record) or [upload existing data sets from CSV](/tables/import-data-into-existing-table) files. |
||||
|
||||
#### Create views |
||||
|
||||
Views are customized ways of displaying your data. You can [create multiple views](/views/create-view) for each table in your base, and each view can have its own set of fields, filters, and layouts. NocoDB offers a variety of view types for custom display, including [Grid](/views/view-types/grid), [Kanban](/views/view-types/kanban), and [Gallery](/views/view-types/gallery). If you are collecting data from a form, you can also create a [Form view](/views/view-types/form) to display the data in a form format. |
||||
|
||||
#### Connect your data sources |
||||
|
||||
Not just creating base & tables from the scratch, NocoDB also allows you to get started quickly by [connecting to your existing data sources](/data-sources/data-source-overview) & bring the comfort of spreadsheet UI to your data source. |
||||
|
||||
### Collaborate with your team |
||||
|
||||
NocoDB makes it easy to collaborate with your team members on your workspaces and bases. You can [invite team members to your workspace](/collaboration/workspace-collaboration) and [share your bases with them](/collaboration/base-collaboration). You can also [assign roles and permissions](/roles-and-permissions/roles-permissions-overview) to your team members to control their access to your bases. |
||||
|
||||
Want to share information publicly? You can [create a public link to your base](/collaboration/share-base) and share it with anyone. You can also [embed your base](/collaboration/share-base#embeddable-frame) on your website or blog. |
||||
|
||||
That's it! You're now ready to harness the power of NocoDB for your data management needs. |
||||
|
||||
|
||||
|
@ -0,0 +1,46 @@
|
||||
--- |
||||
title: 'NocoDB terminologies' |
||||
keywords: ['NocoDB terminologies', 'NocoDB terms', 'NocoDB keywords'] |
||||
--- |
||||
|
||||
|
||||
To maximize your use of NocoDB, it's beneficial to become familiar with some common terms. |
||||
|
||||
Within this section, we've provided straightforward explanations for keywords and phrases that are relevant to NocoDB's functionality and capabilities. This resource is designed to assist you in gaining a deeper understanding of NocoDB as you embark on the process of setting up workspaces, bases, tables, and various other elements within the platform. |
||||
|
||||
[//]: # (TBD : Link) |
||||
|
||||
## Layout |
||||
|
||||
The layout below shows the main parts of NocoDB's user interface. |
||||
|
||||
![image](/img/v2/layout-overview.png) |
||||
|
||||
1. **Sidebar**: This component provides quick access to workspaces, bases, tables, and views, facilitating easy navigation within NocoDB. |
||||
|
||||
2. **Navbar**: In the Navbar, you'll find essential tools like the Switcher, allowing users to switch between data mode and details mode, and the Share button for collaborative workspace and view sharing. |
||||
|
||||
3. **Toolbar**: The Toolbar equips users with various tools to manage records within tables and views effectively. It includes features for sorting, filtering, and editing data, enhancing your control over information. |
||||
|
||||
4. **View Area**: The central workspace where data can be viewed in multiple formats - Grid, Gallery, Kanban or Form. |
||||
|
||||
5. **Footbar**: A pagination bar for navigating between paginated records. |
||||
|
||||
## Terminologies |
||||
|
||||
| Term | Description | |
||||
|-----------------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |
||||
| Base | A base is a collection of one or more tables, often related and linked to one another. Alternative term `Project` | |
||||
| Base Owner | Member who had created base. There can be only one owner for a base & ownership is non-transferable | |
||||
| Base member | Base member with specific access permissions. Alternative term `Member` `User` | |
||||
| Cell | A cell represents the space created where a column and a row intersect within a grid-like structure. It serves as the fundamental unit for storing data | |
||||
| Field | A field or column in a table is a container for values that share the same data type. Alternative term `Column` | |
||||
| Modal | In the context of user interfaces, a modal is a type of dialog or overlay that appears on top of the main content or interface and requires user interaction before the user can proceed. Modals are often used to gather user input, display alerts, or confirm actions. They typically "block" the rest of the interface until the user dismisses them, making them a focused and attention-grabbing element | |
||||
| Record | A record represents a row in a table. Alternative term `Row` | |
||||
| Table | A base is housed in tables, where data is logically arranged into rows and columns. A base can have multiple tables. Alternative term `Model` | |
||||
| Term | Description | |
||||
| View | A view defines how data within a table is presented and interacted with. Default view type is the grid view; other supported view types include form, gallery, and kanban views. | |
||||
| Webhook | A webhook is a mechanism that allows one system to send real-time data to another system or application. It enables automated notifications and data synchronization between different services or platforms by triggering predefined actions or events in response to specific events or updates in the source system. | |
||||
| Workspace Owner | Member who had created workspace. There can be only one owner for a workspace & ownership is non-transferable | |
||||
| Workspace member | Workspace member with specific access permissions. Alternative term `Member` `User` | |
||||
| Workspace | A workspace is a collection of one or more bases. It offers collaborative access to bases by enabling you to bring together interconnected tables, views, and various elements into a unified and organized entity | |
@ -1,72 +0,0 @@
|
||||
--- |
||||
title: 'Upgrading' |
||||
description: 'Upgrading NocoDB : Docker, Node and Homebrew!' |
||||
--- |
||||
|
||||
By default, if `NC_DB` is not specified upon [installation](/getting-started/installation), then SQLite will be used to store metadata. We suggest users to separate the metadata and user data in different databases as pictured in our [architecture](/engineering/architecture). |
||||
|
||||
## Docker |
||||
|
||||
### Find, Stop & Delete NocoDB Docker Container |
||||
|
||||
```bash |
||||
# find NocoDB container ID |
||||
docker ps |
||||
# stop NocoDB container |
||||
docker stop <YOUR_CONTAINER_ID> |
||||
# delete NocoDB container |
||||
docker rm <YOUR_CONTAINER_ID> |
||||
``` |
||||
|
||||
Note: Deleting your docker container without setting `NC_DB` or mounting to a persistent volume for a default SQLite database will result in losing your data. See examples below. |
||||
|
||||
### Find & Remove NocoDB Docker Image |
||||
|
||||
```bash |
||||
# find NocoDB image |
||||
docker images |
||||
# delete NocoDB image |
||||
docker rmi <YOUR_IMAGE_ID> |
||||
``` |
||||
|
||||
### Pull the latest NocoDB image with same environment variables |
||||
|
||||
```bash |
||||
docker run -d -p 8080:8080 \ |
||||
-e NC_DB="<YOUR_NC_DB_URL>" \ |
||||
-e NC_AUTH_JWT_SECRET="<YOUR_NC_AUTH_JWT_SECRET_IF_GIVEN>" \ |
||||
nocodb/nocodb:latest |
||||
``` |
||||
|
||||
Updating nocodb docker container is similar to updating [any other docker containers](https://www.whitesourcesoftware.com/free-developer-tools/blog/update-docker-images/). |
||||
|
||||
### Example: Docker Upgrade |
||||
![Screen Shot 2021-09-16 at 09 23 07](https://user-images.githubusercontent.com/5435402/133578984-53c6b96b-3e8b-4a96-b6c2-36f3c09ffdde.png) |
||||
|
||||
## Node |
||||
|
||||
Updating docker container is similar to updating a npm package. |
||||
|
||||
From your root folder |
||||
|
||||
#### Uninstall NocoDB package |
||||
|
||||
```bash |
||||
npm uninstall nocodb |
||||
``` |
||||
#### Install NocoDB package |
||||
|
||||
```bash |
||||
npm install --save nocodb |
||||
``` |
||||
|
||||
## Homebrew |
||||
|
||||
Run following commands to upgrade Homebrew Nocodb version. |
||||
|
||||
```bash |
||||
# Update the local homebrew formulas |
||||
brew update |
||||
# Upgrade nocodb package |
||||
brew upgrade nocodb |
||||
``` |
@ -0,0 +1,113 @@
|
||||
--- |
||||
title: 'Keyboard shortcuts' |
||||
tags: ['Getting Started', 'Shortcuts', 'Productivity hacks'] |
||||
keywords: ['keyboard shortcuts', 'shortcuts', 'keyboard'] |
||||
--- |
||||
|
||||
## Quick Actions ☁ {#quick-actions} |
||||
|
||||
:::note |
||||
This feature is available only in NocoDB Cloud hosted version. |
||||
::: |
||||
|
||||
`⌘` + `K` (or `Ctrl` + `K` on Windows) is a keyboard shortcut to quickly navigate between different workspace, table, view, or a menu items. For example, if you want to quickly navigate to the "API Tokens" page, you can open Quick Actions menu using ⌘+K, type "Token" in the search box and press enter. |
||||
|
||||
This shortcut is often referred to as "Command-K". It's a great way to save time when you're navigating around NocoDB. |
||||
|
||||
Command-K menu can also be accessed via the "Quick Actions" button in the top left corner of the screen. |
||||
|
||||
![Quick Actions](/img/v2/cmd-k.png) |
||||
|
||||
To navigate within ⌘+K menu, |
||||
- Use `↑` `↓` to navigate between listed items |
||||
- Use `Enter` to select an item |
||||
- Use `Backspace` to move to parent menu |
||||
- Use `Esc` to close the menu |
||||
|
||||
## Recent Views |
||||
|
||||
:::note |
||||
This feature is available only in NocoDB Cloud hosted version. |
||||
::: |
||||
|
||||
Access recently visited views quickly using `⌘` + `L` (or `Ctrl` + `L` on Windows). Search results will be displayed in a modal window; click on the result to open the view. |
||||
|
||||
![Recent Views](/img/v2/cmd-l.png) |
||||
|
||||
To navigate within ⌘+K menu, |
||||
- Use `↑` `↓` to navigate between listed items |
||||
- Use `Enter` to select an item |
||||
- Use `Backspace` to move to parent menu |
||||
- Use `Esc` to close the menu |
||||
|
||||
|
||||
## Search in Docs |
||||
|
||||
:::note |
||||
This feature is available only in NocoDB Cloud hosted version. |
||||
::: |
||||
|
||||
Quickly search through docs from within NocoDB UI using `⌘` + `J` (or `Ctrl` + `J` on Windows). Search results will be displayed in a modal window; click on the result to open the page in a new tab. |
||||
|
||||
To navigate within ⌘+K menu, |
||||
- Use `↑` `↓` to navigate between listed items |
||||
- Use `Enter` to select an item |
||||
- Use `Backspace` to move to parent menu |
||||
- Use `Esc` to close the menu |
||||
|
||||
![Search in Docs](/img/v2/cmd-j.png) |
||||
|
||||
|
||||
## General shortcuts |
||||
| Key | Behaviour | |
||||
|------------:|:--------------------------------| |
||||
| `alt` + `t` | Opens new table modal | |
||||
| `alt` + `c` | Opens new field modal | |
||||
| `alt` + `f` | Toggles fullscreen mode | |
||||
| `alt` + `i` | Opens share button modal | |
||||
| `⌘` + `k` | Opens Quick Actions modal | |
||||
|
||||
|
||||
## Grid view shortcuts |
||||
| Key | Behaviour | |
||||
|----------------:|:-------------------------------------------------------------------------------------| |
||||
| `←` `→` `↑` `↓` | General cell navigation | |
||||
| `Delete` | Clear cell | |
||||
| `Space` | Expand current record | |
||||
| `Tab` | Move to next cell horizontally; if on last cell, move to beginning of next record | |
||||
| `Esc` | Exit cell EDIT mode | |
||||
| `Enter` | Switch cell in focus to EDIT mode; opens modal/picker if cell is associated with one | |
||||
| `⌘` + `↑` | Jump to first record in this field (in same page) | |
||||
| `⌘` + `↓` | Jump to last record in this field (in same page) | |
||||
| `⌘` + `←` | Jump to first field in this record | |
||||
| `⌘` + `→` | Jump to last field in this record | |
||||
| `⌘` + `c` | Copy cell contents | |
||||
| `⌘` + `v` | Paste copied contents | |
||||
| `alt` + `r` | Inserts new record in grid view | |
||||
|
||||
|
||||
## Field type specific shortcuts |
||||
| Datatype | Key | Behaviour | |
||||
|:----------------------:|------------:|:-----------------------------------| |
||||
| Text & Numerical cells | `←` `→` | Move cursor to the left / right | |
||||
| | `↑` `↓` | Move cursor to the beginning / end | |
||||
| Single Select | `↑` `↓` | Move between options | |
||||
| | `Enter` | Select option | |
||||
| Multi Select | `↑` `↓` | Move between options | |
||||
| | `Enter` | Select / deselect option | |
||||
| Link | `↑` `↓` | Move between options | |
||||
| | `Enter` | Link current selection | |
||||
| Checkbox | `Enter` | Toggle | |
||||
| Rating | `<0 ~ Max>` | Enter number to toggle rating | |
||||
|
||||
|
||||
## Expanded form shortcuts |
||||
| Key | Behaviour | |
||||
|--------------:|:----------------------------------| |
||||
| `⌘` + `Enter` | Save current expanded form item | |
||||
| `alt` + `→` | Switch to next record | |
||||
| `alt` + `←` | Switch to previous record | |
||||
| `alt` + `S` | Save current expanded form record | |
||||
| `alt` + `N` | Create a new record | |
||||
|
||||
|
@ -0,0 +1,69 @@
|
||||
--- |
||||
title: 'Environment variables' |
||||
description: 'Environment Variables for NocoDB!' |
||||
hide_table_of_contents: true |
||||
tags: ['Open Source'] |
||||
keywords : ['NocoDB environment variables', 'NocoDB env variables', 'NocoDB envs', 'NocoDB env'] |
||||
--- |
||||
|
||||
For production use-cases, it is **recommended** to configure |
||||
- `NC_DB`, |
||||
- `NC_AUTH_JWT_SECRET`, |
||||
- `NC_PUBLIC_URL`, |
||||
- `NC_REDIS_URL` |
||||
|
||||
| Variable | Comments | If absent | |
||||
|------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------| |
||||
| NC_DB | See our example database URLs [here](https://github.com/nocodb/nocodb#docker). | A local SQLite will be created in root folder if `NC_DB` is not provided | |
||||
| NC_DB_JSON | Can be used instead of `NC_DB` and value should be valid knex connection JSON | | |
||||
| NC_DB_JSON_FILE | Can be used instead of `NC_DB` and value should be a valid path to knex connection JSON | | |
||||
| DATABASE_URL | Can be used instead of `NC_DB` and value should be in JDBC URL format | | |
||||
| DATABASE_URL_FILE | Can be used instead of `DATABASE_URL` and value should be a valid path to file containing JDBC URL format. | | |
||||
| NC_AUTH_JWT_SECRET | JWT secret used for auth and storing other secrets | A random secret will be generated | |
||||
| PORT | For setting app running port | `8080` | |
||||
| DB_QUERY_LIMIT_DEFAULT | Pagination limit | 25 | |
||||
| DB_QUERY_LIMIT_MAX | Maximum allowed pagination limit | 1000 | |
||||
| DB_QUERY_LIMIT_MIN | Minimum allowed pagination limit | 1 | |
||||
| NC_TOOL_DIR | App directory to keep metadata and app related files | Defaults to current working directory. In docker maps to `/usr/app/data/` for mounting volume. | |
||||
| NC_PUBLIC_URL | Used for sending Email invitations | Best guess from http request params | |
||||
| NC_JWT_EXPIRES_IN | JWT token expiry time | `10h` | |
||||
| NC_CONNECT_TO_EXTERNAL_DB_DISABLED | Disable Project creation with external database | | |
||||
| NC_INVITE_ONLY_SIGNUP | Removed since version 0.99.0 and now it's recommended to use [super admin settings menu](/account-settings/oss-specific-details#enable--disable-signup). Allow users to signup only via invite URL, value should be any non-empty string. | | |
||||
| NUXT_PUBLIC_NC_BACKEND_URL | Custom Backend URL | ``http://localhost:8080`` will be used | |
||||
| NC_REQUEST_BODY_SIZE | Request body size [limit](https://expressjs.com/en/resources/middleware/body-parser.html#limit) | `1048576` | |
||||
| NC_EXPORT_MAX_TIMEOUT | After NC_EXPORT_MAX_TIMEOUT, CSV gets downloaded in batches | Default value 5000(in millisecond) will be used | |
||||
| NC_DISABLE_TELE | Disable telemetry | | |
||||
| NC_DASHBOARD_URL | Custom dashboard URL path | `/dashboard` | |
||||
| NC_GOOGLE_CLIENT_ID | Google client ID to enable Google authentication | | |
||||
| NC_GOOGLE_CLIENT_SECRET | Google client secret to enable Google authentication | | |
||||
| NC_MIGRATIONS_DISABLED | Disable NocoDB migration | | |
||||
| NC_MIN | If set to any non-empty string the default splash screen(initial welcome animation) and matrix screensaver will disable | | |
||||
| NC_SENTRY_DSN | For Sentry monitoring | | |
||||
| NC_REDIS_URL | Custom Redis URL. Example: `redis://:authpassword@127.0.0.1:6380/4` | Meta data will be stored in memory | |
||||
| NC_DISABLE_ERR_REPORT | Disable error reporting | | |
||||
| NC_DISABLE_CACHE | To be used only while debugging. On setting this to `true` - meta data be fetched from db instead of redis/cache. | `false` | |
||||
| AWS_ACCESS_KEY_ID | For Litestream - S3 access key id | If Litestream is configured and `NC_DB` is not present. SQLite gets backed up to S3 | |
||||
| AWS_SECRET_ACCESS_KEY | For Litestream - S3 secret access key | If Litestream is configured and `NC_DB` is not present. SQLite gets backed up to S3 | |
||||
| AWS_BUCKET | For Litestream - S3 bucket | If Litestream is configured and `NC_DB` is not present. SQLite gets backed up to S3 | |
||||
| AWS_BUCKET_PATH | For Litestream - S3 bucket path (like folder within S3 bucket) | If Litestream is configured and `NC_DB` is not present. SQLite gets backed up to S3 | |
||||
| NC_SMTP_FROM | For SMTP plugin - Email sender address | | |
||||
| NC_SMTP_HOST | For SMTP plugin - SMTP host value | | |
||||
| NC_SMTP_PORT | For SMTP plugin - SMTP port value | | |
||||
| NC_SMTP_USERNAME | For SMTP plugin (Optional) - SMTP username value for authentication | | |
||||
| NC_SMTP_PASSWORD | For SMTP plugin (Optional) - SMTP password value for authentication | | |
||||
| NC_SMTP_SECURE | For SMTP plugin (Optional) - To enable secure set value as `true` any other value treated as false | | |
||||
| NC_SMTP_IGNORE_TLS | For SMTP plugin (Optional) - To ignore tls set value as `true` any other value treated as false. For more info visit https://nodemailer.com/smtp/ | | |
||||
| NC_S3_BUCKET_NAME | For S3 storage plugin - AWS S3 bucket name | | |
||||
| NC_S3_REGION | For S3 storage plugin - AWS S3 region | | |
||||
| NC_S3_ACCESS_KEY | For S3 storage plugin - AWS access key credential for accessing resource | | |
||||
| NC_S3_ACCESS_SECRET | For S3 storage plugin - AWS access secret credential for accessing resource | | |
||||
| NC_ADMIN_EMAIL | For updating/creating super admin with provided email and password | | |
||||
| NC_ATTACHMENT_FIELD_SIZE | For setting the attachment field size(in Bytes) | Defaults to 20MB | |
||||
| NC_ADMIN_PASSWORD | For updating/creating super admin with provided email and password. Your password should have at least 8 letters with one uppercase, one number and one special letter(Allowed special chars $&+,:;=?@#\|'.^*()%!_-" ) | | |
||||
| NODE_OPTIONS | For passing Node.js [options](https://nodejs.org/api/cli.html#node_optionsoptions) to instance | | |
||||
| NC_MINIMAL_DBS | Create a new SQLite file for each project. All the db files are stored in `nc_minimal_dbs` folder in current working directory. (This option restricts project creation on external sources) | | |
||||
| NC_DISABLE_AUDIT | Disable Audit Log | `false` | |
||||
| NC_AUTOMATION_LOG_LEVEL | Possible Values: `OFF`, `ERROR`, `ALL`. See [Webhooks](/automation/webhook/create-webhook#call-log) for details. | `OFF` | |
||||
| NC_SECURE_ATTACHMENTS | Allow accessing attachments only through presigned urls. To enable set value as `true` any other value treated as false. (⚠ this will make existing links inaccessible ⚠) | `false` | |
||||
| NC_ATTACHMENT_EXPIRE_SECONDS | How many seconds before expiring presigned attachment urls. (Attachments will expire in at least set seconds and at most 10mins after set time) | 7200 (2 hours) | |
||||
| NC_ALLOW_LOCAL_HOOKS | To enable set value as `true` any other value treated as false. (⚠ this will allow webhooks to call local links which can raise security issues ⚠) | `false` | |
@ -0,0 +1,149 @@
|
||||
--- |
||||
title: 'Upgrading' |
||||
description: 'Upgrading NocoDB : Docker, Node and Homebrew!' |
||||
tags: ['Open Source'] |
||||
keywords: ['NocoDB upgrade', 'upgrade NocoDB', 'upgrade nocodb'] |
||||
--- |
||||
|
||||
By default, if `NC_DB` is not specified upon [installation](/getting-started/self-hosted/installation), then SQLite will be used to store metadata. We suggest users to separate the metadata and user data in different databases as pictured in our [architecture](/engineering/architecture). |
||||
|
||||
## Docker |
||||
|
||||
### Find, Stop & Delete NocoDB Docker Container |
||||
|
||||
```bash |
||||
# find NocoDB container ID |
||||
docker ps |
||||
# stop NocoDB container |
||||
docker stop <YOUR_CONTAINER_ID> |
||||
# delete NocoDB container |
||||
docker rm <YOUR_CONTAINER_ID> |
||||
``` |
||||
|
||||
Note: Deleting your docker container without setting `NC_DB` or mounting to a persistent volume for a default SQLite database will result in losing your data. See examples below. |
||||
|
||||
### Find & Remove NocoDB Docker Image |
||||
|
||||
```bash |
||||
# find NocoDB image |
||||
docker images |
||||
# delete NocoDB image |
||||
docker rmi <YOUR_IMAGE_ID> |
||||
``` |
||||
|
||||
### Pull the latest NocoDB image with same environment variables |
||||
|
||||
```bash |
||||
docker run -d -p 8080:8080 \ |
||||
-e NC_DB="<YOUR_NC_DB_URL>" \ |
||||
-e NC_AUTH_JWT_SECRET="<YOUR_NC_AUTH_JWT_SECRET_IF_GIVEN>" \ |
||||
nocodb/nocodb:latest |
||||
``` |
||||
|
||||
Updating NocoDB docker container is similar to updating [any other docker containers](https://www.whitesourcesoftware.com/free-developer-tools/blog/update-docker-images/). |
||||
|
||||
### Example: Docker Upgrade |
||||
|
||||
```bash |
||||
# Previous docker run |
||||
# |
||||
terminal % docker run -d --name myNocoDB \ |
||||
-v "$(pwd)"/nocodb:/usr/app/data/ \ |
||||
-p 8080:8080 \ |
||||
-e NC_DB="pg://host.docker.internal:5432?u=postgres&p=password&d=d1" \ |
||||
-e NC_AUTH_JWT_SECRET="569a1821-0a93-45e8-87ab-eb857f20a010" \ |
||||
nocodb/nocodb:0.111.0 |
||||
Unable to find image 'nocodb/nocodb:0.111.0' locally |
||||
0.111.0: Pulling from nocodb/nocodb |
||||
ad3fa0ea069c: Pull complete |
||||
e43b9156e769: Pull complete |
||||
c1bee0da1504: Pull complete |
||||
adf78ab024d9: Pull complete |
||||
cd8000d2c16a: Pull complete |
||||
Digest: sha256:93b6e1ba2c0b90a26b205f9c7d44053aa6d8fa037eff9eb4155ca017f6c9bed4 |
||||
Status: Downloaded newer image for nocodb/nocodb:0.111.0 |
||||
afdc8edd1005c93e1df8f90d02e46430ea7b5c5610a2bf9ba105238d6c4d927b |
||||
|
||||
|
||||
# Find, stop and delete NocoDB docker container |
||||
# |
||||
terminal % docker ps |
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES |
||||
afdc8edd1005 nocodb/nocodb:0.111.0 "/usr/bin/dumb-init …" 18 seconds ago Up 18 seconds 0.0.0.0:8080->8080/tcp myNocoDB |
||||
0202041b3607 postgres:14.7 "docker-entrypoint.s…" 2 days ago Up 8 hours (healthy) 0.0.0.0:5432->5432/tcp scripts_pg147_1 |
||||
|
||||
terminal % docker stop afdc8edd1005 |
||||
afdc8edd1005 |
||||
|
||||
terminal % docker rm afdc8edd1005 |
||||
afdc8edd1005 |
||||
|
||||
|
||||
# Find and remove NocoDB docker image |
||||
# |
||||
terminal % docker images |
||||
REPOSITORY TAG IMAGE ID CREATED SIZE |
||||
nocodb/nocodb 0.111.0 34609411e87c 5 weeks ago 132MB |
||||
mysql 8.0 6a0560a40914 7 weeks ago 599MB |
||||
postgres 14.7 2075a95c7b3b 4 months ago 358MB |
||||
|
||||
terminal % docker rmi 34609411e87c |
||||
Untagged: nocodb/nocodb:0.111.0 |
||||
Untagged: nocodb/nocodb@sha256:93b6e1ba2c0b90a26b205f9c7d44053aa6d8fa037eff9eb4155ca017f6c9bed4 |
||||
Deleted: sha256:3bfxxxx38e682742cbxxxx535b3503af45e931fb9bd15f46eca7d33cf4c54d72 |
||||
Deleted: sha256:952152b5da42ae057c6688a04xxxx72e1a2f91825956f5c7e35f91d5b285d4d8 |
||||
Deleted: sha256:3155197577xxxx673675ed1bce761714a24d7803f70a905740f7d4c248cxxxxx |
||||
|
||||
|
||||
# Pull & run the latest NocoDB image with same environment variables as before |
||||
# |
||||
terminal % docker run -d --name myNocoDB \ |
||||
-v "$(pwd)"/nocodb:/usr/app/data/ \ |
||||
-p 8080:8080 \ |
||||
-e NC_DB="pg://host.docker.internal:5432?u=postgres&p=password&d=d1" \ |
||||
-e NC_AUTH_JWT_SECRET="569a1821-0a93-45e8-87ab-eb857f20a010" \ |
||||
nocodb/nocodb:latest |
||||
Unable to find image 'nocodb/nocodb:latest' locally |
||||
latest: Pulling from nocodb/nocodb |
||||
ad3fa0ea069c: Pull complete |
||||
e43b9156e769: Pull complete |
||||
c1bee0da1504: Pull complete |
||||
adf78ab024d9: Pull complete |
||||
28ce4fc94e48: Pull complete |
||||
Digest: sha256:5c6df5ff0eb1278e1dbfe684af630a743ca73dfec8c30cab3bae9c1d0d640287 |
||||
Status: Downloaded newer image for nocodb/nocodb:latest |
||||
ae793a04b75f2f3ee78abbaef09891396a884ec83320151a266326195649a058 |
||||
|
||||
|
||||
``` |
||||
|
||||
|
||||
## Node |
||||
|
||||
Updating docker container is similar to updating a npm package. |
||||
|
||||
From your root folder |
||||
|
||||
#### Uninstall NocoDB package |
||||
|
||||
```bash |
||||
npm uninstall nocodb |
||||
``` |
||||
#### Install NocoDB package |
||||
|
||||
```bash |
||||
npm install --save nocodb |
||||
``` |
||||
|
||||
## Homebrew |
||||
|
||||
Run following commands to upgrade Homebrew Nocodb version. |
||||
|
||||
```bash |
||||
# Update the local homebrew formulas |
||||
brew update |
||||
# Upgrade nocodb package |
||||
brew upgrade nocodb |
||||
``` |
||||
|
||||
|
@ -0,0 +1,5 @@
|
||||
{ |
||||
"label": "In Open Source", |
||||
"collapsible": true, |
||||
"collapsed": false |
||||
} |
@ -1,5 +1,5 @@
|
||||
{ |
||||
"label": "Getting Started", |
||||
"collapsible": true, |
||||
"collapsed": false |
||||
"collapsed": true |
||||
} |
@ -1,101 +0,0 @@
|
||||
--- |
||||
title: 'Dashboard' |
||||
description: 'Accessing the Dashboard!' |
||||
--- |
||||
|
||||
## Setup Your First Super Admin |
||||
|
||||
Once you have started NocoDB, you can visit the dashboard via `example.com`. You will be redirected to `example.com/#/signup`. |
||||
|
||||
Enter your work email and your password. |
||||
|
||||
![signup](https://github.com/nocodb/nocodb/assets/86527202/f424f935-fef2-4080-8b67-3f6f1bd95c65) |
||||
|
||||
:::info |
||||
|
||||
Your password has at least 8 letters. No other constraints on case, numbers or special characters. |
||||
|
||||
::: |
||||
|
||||
On signup, landing page has a default project & a table created for you to quickly get started |
||||
|
||||
![landing page](https://github.com/nocodb/nocodb/assets/86527202/cd09dbeb-f5e1-42e6-92bb-abd4b3ab48bf) |
||||
|
||||
The data will be stored in `NC_DB`. If it is not specified, a local SQLite will be created and used. |
||||
|
||||
:::info |
||||
|
||||
NC_DB is an environment variable used to store the metadata. |
||||
|
||||
::: |
||||
|
||||
|
||||
### Connecting to External Database |
||||
|
||||
Click on project title in left sidebar to open the project dashboard. On the project dashboard, open `Data Sources` tab. Click on `+ New Source` button to add existing database. |
||||
|
||||
:::tip |
||||
|
||||
If you are running NocoDB on Docker and your local DB is running on your host machine, your Host Address would be host.docker.internal instead of localhost. |
||||
|
||||
::: |
||||
|
||||
|
||||
![data source](/img/content/data-source.png) |
||||
|
||||
|
||||
You need to specify the project name, API type, and other database parameters. |
||||
|
||||
![extDB connection modal](/img/content/extDB-connection-modal.png) |
||||
|
||||
|
||||
Currently it supports MySQL, Postgres, MSSQL and SQLite. |
||||
|
||||
You can also configure associated SSL & advanced parameters. |
||||
|
||||
<img width="689" alt="image" src="https://user-images.githubusercontent.com/35857179/189047293-05176c44-e162-495a-a7cd-e02377c1f42c.png" /> |
||||
|
||||
|
||||
:::tip |
||||
|
||||
You can click Edit Connection JSON and modify SSL settings in "ssl". |
||||
|
||||
::: |
||||
|
||||
```json |
||||
{ |
||||
"client": "pg", |
||||
"connection": { |
||||
"host": "<YOUR_HOST>", |
||||
"port": "5432", |
||||
"user": "<YOUR_DB_USER>", |
||||
"password": "<YOUR_DB_PASSWORD>", |
||||
"database": "<YOUR_DB_NAME>", |
||||
"ssl": { |
||||
"require": true, |
||||
"rejectUnauthorized": false, |
||||
"sslMode": "no-verify" |
||||
} |
||||
} |
||||
} |
||||
``` |
||||
|
||||
:::tip |
||||
|
||||
You can click Edit Connection JSON and specify the schema you want to use in "searchPath". |
||||
|
||||
::: |
||||
|
||||
```json |
||||
{ |
||||
"client": "pg", |
||||
"connection": { |
||||
... |
||||
}, |
||||
"searchPath": [ "<YOUR_TARGET_SCHEMA>" ] |
||||
} |
||||
``` |
||||
|
||||
Click `Test Database Connection` to see if the connection can be established or not. NocoDB creates a new **empty database** with specified parameters if the database doesn't exist. |
||||
|
||||
<img width="505" alt="image" src="https://user-images.githubusercontent.com/35857179/194793513-feabf14f-1f62-4896-b06d-88548251511a.png" /> |
@ -1,204 +0,0 @@
|
||||
--- |
||||
title: "Table Operations" |
||||
description: "Table Operations: Row, Column, Quick Import, Export & Import" |
||||
--- |
||||
|
||||
Once you have created a new NocoDB project you can open it, In the browser, the URL would be like `example.com/#/default/<project_id>`. |
||||
|
||||
## Table |
||||
|
||||
### Table Create |
||||
|
||||
On project dashboard, click on `Add new table` button |
||||
|
||||
![table-create-button](https://github.com/nocodb/nocodb/assets/86527202/0b1d0b89-b3c6-4c3c-8208-4b6afce67d23) |
||||
|
||||
Provide a name for the table & click `Create Table` button. |
||||
|
||||
![table-create-modal](https://github.com/nocodb/nocodb/assets/86527202/fceb6c48-e0d6-428c-bb16-d2da4e38a81f) |
||||
|
||||
After the successful submission, the table will be created and open on a new grid. |
||||
|
||||
![new-table-landing-page](https://github.com/nocodb/nocodb/assets/86527202/96ffae6f-c18f-4b80-81eb-847cfb8116e2) |
||||
|
||||
New table can also be created by using `+` button on project tile in left sidebar |
||||
|
||||
![new-table-on-hover](https://github.com/nocodb/nocodb/assets/86527202/5a4ce91b-f4bf-451c-8835-8e7144deec26) |
||||
|
||||
|
||||
### Table Rename |
||||
|
||||
Right click on Table name on left sidebar, (OR) |
||||
Click on `...` to open `Table context menu`, select `Rename`. |
||||
Feed in the changes to the table name & press `Enter` |
||||
|
||||
![table-context-menu](https://github.com/nocodb/nocodb/assets/86527202/67cb7563-5a10-4d91-bc83-b31ff185d18d) |
||||
|
||||
### Table Duplicate |
||||
|
||||
Right click on Table name on left sidebar, (OR) |
||||
Click on `...` to open `Table context menu`, select `Duplicate` |
||||
|
||||
![table-context-menu](https://github.com/nocodb/nocodb/assets/86527202/67cb7563-5a10-4d91-bc83-b31ff185d18d) |
||||
|
||||
Additionally, you can configure to duplicate |
||||
- `Include Data` : toggle this to include/exclude table records |
||||
- `Include Views` : toggle this to include/exclude table views |
||||
|
||||
![table-duplicate-modal](https://github.com/nocodb/nocodb/assets/86527202/e668c382-530f-423c-9de7-f68896a6ba67) |
||||
|
||||
### Table Delete |
||||
|
||||
Right click on Table name on left sidebar, (OR) |
||||
Click on `...` to open `Table context menu`, select `Delete` |
||||
|
||||
![table-context-menu](https://github.com/nocodb/nocodb/assets/86527202/67cb7563-5a10-4d91-bc83-b31ff185d18d) |
||||
|
||||
Click on `Delete Table` to confirm |
||||
|
||||
![table-delete-confirmation-modal](https://github.com/nocodb/nocodb/assets/86527202/a0d11ca6-0aed-4eaf-a855-c49ff987d546) |
||||
|
||||
## Column |
||||
|
||||
### Column Add |
||||
|
||||
Click on `+` button to the right of Columns header, type `Column name` |
||||
|
||||
![column-add](https://github.com/nocodb/nocodb/assets/86527202/d3350116-5047-4385-8eab-1fef4b3836ac) |
||||
|
||||
Select a `type` for the column from the dropdown. Depending on the column type, you might find additional options to configure. |
||||
Click on `Save column` to finish creating column. |
||||
|
||||
![column-add-type](https://github.com/nocodb/nocodb/assets/86527202/239bfbde-fd20-4f8e-966c-2c60507c195e) |
||||
|
||||
#### Column create before OR after a specific column |
||||
You can also use context menu of an existing column to either insert before or after a specific column. |
||||
![column-context-menu - insert after before](https://github.com/nocodb/nocodb/assets/86527202/d15b62b4-5302-4c75-bd5b-e60ae8b81a65) |
||||
|
||||
|
||||
### Column Edit |
||||
|
||||
Double click on Column name in column header to open `Column edit` modal |
||||
You can rename column & optionally change column-type. |
||||
|
||||
![column-rename](https://github.com/nocodb/nocodb/assets/86527202/1a0f798e-6726-4810-9645-e531a88e495a) |
||||
|
||||
Note: |
||||
- Changing column type might not be allowed in some scenarios & in some other, might lead to either loss or truncated data. |
||||
- Column name is also possible using Column context menu as described below |
||||
|
||||
|
||||
### Column Duplicate |
||||
|
||||
Open `Column context menu` (click `v` on column header), select `Duplicate` |
||||
|
||||
![column-duplicate](https://github.com/nocodb/nocodb/assets/86527202/8d1f36e6-5f6b-4f89-81d0-c0d3148bd056) |
||||
|
||||
Note: Column duplicate only creates another column of same type & inserts it to the immediate right. Currently data in the column is not duplicated. |
||||
|
||||
|
||||
### Column Delete |
||||
|
||||
Open `Column context menu` (click `v` on column header), select `Delete` |
||||
|
||||
![column-delete](https://github.com/nocodb/nocodb/assets/86527202/2444124d-f12a-4bab-91ce-9b8c0625a263) |
||||
|
||||
Click on `Delete Column` to confirm |
||||
|
||||
![Column delete confirmation modal](https://github.com/nocodb/nocodb/assets/86527202/5675b2ef-9d2c-40fe-900b-d5dd58d1655d) |
||||
|
||||
## Row |
||||
|
||||
For adding new values to the table we need new rows, new rows can be added in two methods. |
||||
|
||||
### Row Add (Using Form) |
||||
Click on `New Record` at the bottom of the grid (footbar), select `New Record - Form` |
||||
![new record-form](https://github.com/nocodb/nocodb/assets/86527202/c6e9acff-4d54-440a-9888-e24529747cf9) |
||||
|
||||
Populate columns in the Expnaded form popup; click `Save` |
||||
![expanded record form](https://github.com/nocodb/nocodb/assets/86527202/ec264f05-8b0b-4029-adc0-a88932d69c9f) |
||||
|
||||
### Row Add (Using Table Row at bottom of page) |
||||
![in grid insert](https://github.com/nocodb/nocodb/assets/86527202/cf0b6ccb-f598-4874-bb87-8fe291bab14e) |
||||
|
||||
Click on any of the following options to insert a new record on the grid directly. |
||||
- `+` |
||||
- `New Record` : `New Record- Grid` |
||||
- Right click on any cell, click `Insert new row` from the cell context menu |
||||
|
||||
Note that, any record inserted in the grid will always be appended to the end of the table by default. |
||||
|
||||
### Row Add (Pressing Enter Key from Previous Row) |
||||
|
||||
When you finish editing a cell and press Enter, the cell in the next row with the same column will be highlighted. |
||||
|
||||
![image](https://user-images.githubusercontent.com/35857179/203271676-bab64ca4-e0e4-4deb-9a62-609a97158911.png) |
||||
|
||||
### Row Edit |
||||
|
||||
You can start editing by any of the following methods |
||||
- Double-click on cell to edit |
||||
- Click on cell and start typing (this way it will clear the previous content) |
||||
- Click on cell and press enter to start editing |
||||
- And it will automatically save on blur event or if inactive. |
||||
|
||||
### Row Delete |
||||
|
||||
Right-click on the row and then from the context menu select `Delete Row` option. |
||||
![delete row -1](https://github.com/nocodb/nocodb/assets/86527202/9eef834b-21cf-4828-90ec-3c2e86cd19db) |
||||
|
||||
Bulk delete is also possible by selecting multiple rows by using the checkbox in first column and then `Delete Selected Rows` options from the right click context menu. |
||||
![delete row 2](https://github.com/nocodb/nocodb/assets/86527202/f83c702a-fa75-42a5-86eb-22ed85c0dec1) |
||||
|
||||
## Quick Import |
||||
|
||||
You can use Quick Import when you have data from external sources such as Airtable, CSV file or Microsoft Excel to an existing project by either |
||||
|
||||
- Hover on `Project title` in tree-view, click `...` > `Quick Import From` > `Airtable` or `CSV file` or `Microsoft Excel` or `JSON file` |
||||
- Drag and drop CSV, JSON or Excel file to import |
||||
|
||||
![image](/img/content/quick-import.png) |
||||
|
||||
### Import Airtable into an Existing Project |
||||
|
||||
- See [here](/setup-and-usages/import-airtable-to-sql-database-within-a-minute-for-free) |
||||
|
||||
### Import CSV data into an Existing Project |
||||
|
||||
- Hover on `Project title` in tree-view, click `...` > `Quick Import From` > `CSV file` |
||||
- Drag & drop or select files (at most 5 files) to upload or specify CSV file URL, and Click Import |
||||
- **Auto-Select Field Types**: If it is checked, column types will be detected. Otherwise, it will default to `SingleLineText`. |
||||
- **Use First Row as Headers**: If it is checked, the first row will be treated as header row. |
||||
- **Import Data**: If it is checked, all data will be imported. Otherwise, only table will be created. |
||||
![image](/img/content/import-csv.png) |
||||
- You can revise the table name by double-clicking it, column name and column type. By default, the first column will be chosen as `Display Value` and cannot be deleted. |
||||
![image](/img/content/import-csv-2.png) |
||||
- Click `Import` to start importing process. The table will be created and the data will be imported. |
||||
![image](/img/content/import-csv-3.png) |
||||
|
||||
### Import Excel data into an Existing Project |
||||
|
||||
|
||||
- Hover on `Project title` in tree-view, click `...` > `Quick Import From` > `Excel file` |
||||
- Drag & drop or select files (at most 5 files) to upload or specify CSV file URL, and Click Import |
||||
- **Auto-Select Field Types**: If it is checked, column types will be detected. Otherwise, it will default to `SingleLineText`. |
||||
- **Use First Row as Headers**: If it is checked, the first row will be treated as header row. |
||||
- **Import Data**: If it is checked, all data will be imported. Otherwise, only table will be created. |
||||
![image](/img/content/import-xls.png) |
||||
- You can revise the table name by double-clicking it, column name and column type. By default, the first column will be chosen as `Display Value` and cannot be deleted. |
||||
![image](/img/content/import-xls-2.png) |
||||
- Click `Import` to start importing process. The table will be created and the data will be imported. |
||||
![image](/img/content/import-xls-3.png) |
||||
|
||||
## Export Data |
||||
|
||||
You can export your data from a table as a CSV file by clicking the `...` menu in toolbar, and hover on `Download`. Currently only CSV and XLSX formats are supported for export. |
||||
|
||||
![image](/img/content/export.png) |
||||
|
||||
## Import Data |
||||
|
||||
You can export your data from a table as a CSV file by clicking the `...` menu in toolbar, and hover on `Upload`. Currently only CSV and XLSX formats are supported for import. |
||||
|
||||
![image](/img/content/import.png) |
||||
|
@ -1,133 +0,0 @@
|
||||
--- |
||||
title: "Column Operations" |
||||
description: "Column Operations: Fields, Sort & Filter" |
||||
--- |
||||
|
||||
## Fields |
||||
|
||||
Click `Fields` to control the visibility of a field. |
||||
|
||||
By default, all system fields will be hid. However, you can tick `Show system fields` to make them visible. |
||||
|
||||
<img width="1268" alt="image" src="https://user-images.githubusercontent.com/86527202/262226113-6ad574c2-93d0-49ac-be28-01b336df8de4.png" /> |
||||
|
||||
### Re-order Columns |
||||
|
||||
Column positions can be re-ordered. Open `Fields` menu, and re-order fields as needed by dragging and dropping the `drag icon`. |
||||
|
||||
<img width="1268" alt="image" src="https://user-images.githubusercontent.com/86527202/262226232-0b30d4b2-3390-470f-bf01-72b5b922726b.png" /> |
||||
|
||||
### Hide / Unhide Columns |
||||
|
||||
To hide / un-hide columns, open Fields menu, click on associated toggle button to hide / un-hide. |
||||
|
||||
:::tip |
||||
|
||||
You can create different grid views with different fields shown in each view. |
||||
|
||||
::: |
||||
|
||||
<img alt="image" src="https://user-images.githubusercontent.com/86527202/262226271-b9a323e9-39b8-418d-9b7c-3da0f2d17d89.png" /> |
||||
|
||||
<!-- #### Demo --> |
||||
|
||||
<!-- <img src="https://github.com/dstala/nocodb-files/blob/2c4ca2ff31460ee5636262e88ba303e2d436ba54/ColumnHide.gif?raw=true" width="100%"/> -- /> |
||||
<!-- img src="https://media2.giphy.com/media/8NXvWfHDoul72dwLhk/giphy.gif?cid=790b76116fa008b45c79bb91bfe611e324fa38cde21a255a&rid=giphy.gif&ct=g" width="60%"/ --> |
||||
|
||||
## Sort |
||||
|
||||
Sorting allows you to order contents alphabetically (A → Z) / (Z → A) (OR) in ascending / descending order. NocoDB allows nested sorting. You can choose column fields & order in which to apply nested sorting. Lookup, Formula, Nested Data are also supported in Sorting. |
||||
|
||||
### Add / Edit sort |
||||
|
||||
- Click on `Sort` button in the toolbar menu |
||||
- Select `Field` to sort by |
||||
|
||||
|
||||
![sort](https://github.com/nocodb/nocodb/assets/86527202/5665b5db-7d66-4d17-8307-4a8bf32360c8) |
||||
|
||||
- Configure sort `direction` |
||||
|
||||
|
||||
![sort direction](https://github.com/nocodb/nocodb/assets/86527202/56a6d29b-de43-4aaf-b77e-41f32bb58f93) |
||||
|
||||
- Multiple fields can be configured for subsequent level sorting |
||||
|
||||
|
||||
![sort nested](https://github.com/nocodb/nocodb/assets/86527202/4e9393d7-953c-4a3f-bb4e-3b0161042ae4) |
||||
|
||||
|
||||
Note: Field configured on the top will be used for first level sorting, followed by subsequent fields in top-down order |
||||
|
||||
### Delete sort |
||||
- Click on `Sort` button in the toolbar |
||||
- Click on the bin icon to the right of the sort you wish to delete |
||||
|
||||
![sort delete](https://github.com/nocodb/nocodb/assets/86527202/d469110b-12b2-4b8a-83ee-fe8819da2dc1) |
||||
|
||||
|
||||
## Filter |
||||
|
||||
Filters allow you to restrict / organize your data on the view as per your needs. NocoDB allows nested filters. You can choose multiple columns and conditions to apply filter. Between filters, you can opt for either `and` or `or` mode operation. Lookup, Formula, Nested Data are also supported in Filtering. |
||||
|
||||
### Add / Edit filter |
||||
Click on `Filter` button in the toolbar, select either `Add filter` or `Add filter group` |
||||
|
||||
![filter add](https://github.com/nocodb/nocodb/assets/86527202/f312d8e5-98f1-4e34-ad82-460bb5eacef3) |
||||
|
||||
Configure filter : `Column` `Operation` and `Value` (if applicable) |
||||
|
||||
![filter level-1](https://github.com/nocodb/nocodb/assets/86527202/62ac5ea5-64c7-4ab4-93bc-c2897e1a9122) |
||||
|
||||
Multiple filter conditions can be combined by using either `and` or `or` mode of operation |
||||
|
||||
![filter nested](https://github.com/nocodb/nocodb/assets/86527202/1e9af5bf-c19f-49ed-8fc4-a62093f6ee01) |
||||
|
||||
### Delete filter |
||||
|
||||
To delete a filter, click on the bin icon to the right of the associated filter |
||||
|
||||
![filter delete](https://github.com/nocodb/nocodb/assets/86527202/c8f5abac-a550-4152-ab51-5f0765cd188b) |
||||
|
||||
|
||||
### Grouped filters |
||||
You can also group several filters together using Filter Group. |
||||
|
||||
![filter grouped](https://github.com/nocodb/nocodb/assets/86527202/582c29de-28cd-4414-b7db-4b1b1eea131e) |
||||
|
||||
## Enable NULL and EMPTY Filters |
||||
NULL filters (`is null` & `is not null`) and EMPTY filters (`is empty` & `is not empty`) are hidden by default. If you wish to filter out either one only, you may enable `Show NULL and EMPTY Filter` in Project Settings. |
||||
|
||||
![project settings](https://github.com/nocodb/nocodb/assets/86527202/49d40f16-f8bd-4925-a4d0-65efb2d8f73e) |
||||
|
||||
![filters show null empty](https://github.com/nocodb/nocodb/assets/86527202/a383f5e8-f2b9-461b-b725-9b172ac9975b) |
||||
|
||||
Otherwise, we can use Blank filters to filter out cells with NULL values and EMPTY values. |
||||
|
||||
### Supported Filters |
||||
|
||||
Currently, we support different types of filters for corresponding columns. Please refer the below matrix for details. |
||||
|
||||
<iframe width="100%" height="700vh" src="https://docs.google.com/spreadsheets/d/e/2PACX-1vTpCNKtA-szaXUKJEO5uuSIRnzUOK793MKnyBz9m2rQcwn7HqK19jPHeER-IIRWH9X56J78wfxXZuuv/pubhtml?gid=427284630&single=true&widget=true&headers=false"></iframe> |
||||
|
||||
## Group by |
||||
Group-by allows one to visually categorise records on grid into specific `Groups` & `Sub groups`. NocoDB allows three levels of record seggregation. |
||||
|
||||
![group by](https://github.com/nocodb/nocodb/assets/86527202/d4bfcdee-85ed-4c98-92ac-12055f9715e4) |
||||
|
||||
### Add / Edit group-by |
||||
- Click on `Group By` in the toolbar |
||||
- Choose field for the records to be grouped by |
||||
- Optionally- you can also sort groups, in either ascending or descending way. |
||||
- Add sub-groups of upto 3 levels |
||||
|
||||
### Delete group-by |
||||
- Click on `Group By` in the toolbar |
||||
- Click on the bin icon to the right of the group you wish to delete |
||||
|
||||
Note: To disable `Group by` & return back to standard spreadsheet grid view - you need to remove all the groups configured. |
||||
|
||||
## Row Height |
||||
NocoDB allows you to change height of records displayed on spreadsheet grid to 4 different levels `Short` (default), `Medium`, `Tall`, and `Extra`. This allows you to bring more content per cell to be displayed, useful when working with lengthy text columns and multi select fields. |
||||
|
||||
![Row height](https://github.com/nocodb/nocodb/assets/86527202/6f49e7b4-a3de-4325-a11e-3ffc670ddd2e) |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue