mirror of https://github.com/nocodb/nocodb
Pranav C
2 years ago
committed by
GitHub
19 changed files with 536 additions and 2353 deletions
@ -1,126 +0,0 @@
|
||||
<script> |
||||
import ListChildItems from './ListChildItems.vue' |
||||
|
||||
export default { |
||||
name: 'ListChildItemsModal', |
||||
components: { ListChildItems }, |
||||
props: { |
||||
type: String, |
||||
readOnly: Boolean, |
||||
localState: Array, |
||||
isNew: Boolean, |
||||
password: String, |
||||
value: Boolean, |
||||
title: { |
||||
type: String, |
||||
default: 'Link Record', |
||||
}, |
||||
queryParams: { |
||||
type: Object, |
||||
default() { |
||||
return {} |
||||
}, |
||||
}, |
||||
primaryKey: String, |
||||
primaryCol: String, |
||||
meta: Object, |
||||
parentMeta: Object, |
||||
size: Number, |
||||
api: [Object, Function], |
||||
mm: [Object, Boolean], |
||||
isPublic: Boolean, |
||||
rowId: [String, Number], |
||||
column: Object, |
||||
}, |
||||
emits: ['input'], |
||||
data: () => ({ |
||||
data: null, |
||||
page: 1, |
||||
}), |
||||
computed: { |
||||
show: { |
||||
set(v) { |
||||
this.$emit('input', v) |
||||
}, |
||||
get() { |
||||
return this.value |
||||
}, |
||||
}, |
||||
}, |
||||
mounted() {}, |
||||
methods: { |
||||
async loadData() { |
||||
if (this.$refs && this.$refs.child) { |
||||
await this.$refs.child.loadData() |
||||
} |
||||
}, |
||||
}, |
||||
} |
||||
</script> |
||||
|
||||
<template> |
||||
<v-dialog v-model="show" width="600" content-class="dialog"> |
||||
<v-icon small class="close-icon" @click="$emit('input', false)"> mdi-close </v-icon> |
||||
<ListChildItems |
||||
v-if="show" |
||||
ref="child" |
||||
:type="type" |
||||
:row-id="rowId" |
||||
:local-state="localState" |
||||
:is-new="isNew" |
||||
:size="10" |
||||
:meta="meta" |
||||
:password="password" |
||||
:parent-meta="parentMeta" |
||||
:primary-col="primaryCol" |
||||
:primary-key="primaryKey" |
||||
:api="api" |
||||
:query-params="queryParams" |
||||
v-bind="$attrs" |
||||
:read-only="readOnly" |
||||
:is-public="isPublic" |
||||
:column="column" |
||||
/> |
||||
</v-dialog> |
||||
</template> |
||||
|
||||
<style scoped lang="scss"> |
||||
::v-deep { |
||||
.dialog { |
||||
position: relative; |
||||
|
||||
.close-icon { |
||||
width: auto; |
||||
position: absolute; |
||||
right: 10px; |
||||
top: 10px; |
||||
z-index: 9; |
||||
} |
||||
} |
||||
} |
||||
</style> |
||||
|
||||
<!-- |
||||
/** |
||||
* @copyright Copyright (c) 2021, Xgene Cloud Ltd |
||||
* |
||||
* @author Naveen MR <oof1lab@gmail.com> |
||||
* @author Pranav C Balan <pranavxc@gmail.com> |
||||
* |
||||
* @license GNU AGPL version 3 or any later version |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License as |
||||
* published by the Free Software Foundation, either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
--> |
@ -1,19 +0,0 @@
|
||||
import type { ColumnType, TableType } from 'nocodb-sdk' |
||||
import { useMetas } from './useMetas' |
||||
|
||||
export function useBelongsTo(column: ColumnType) { |
||||
const { metas, getMeta } = useMetas() |
||||
const parentMeta = computed<TableType>(() => { |
||||
return metas.value?.[(column.colOptions as any)?.fk_related_model_id as string] |
||||
}) |
||||
|
||||
const loadParentMeta = async () => { |
||||
await getMeta((column.colOptions as any)?.fk_related_model_id as string) |
||||
} |
||||
|
||||
const primaryValueProp = computed(() => { |
||||
return (parentMeta?.value?.columns?.find((c) => c.pv) || parentMeta?.value?.columns?.[0])?.title |
||||
}) |
||||
|
||||
return { parentMeta, loadParentMeta, primaryValueProp } |
||||
} |
@ -1,19 +0,0 @@
|
||||
import type { ColumnType, TableType } from 'nocodb-sdk' |
||||
import { useMetas } from './useMetas' |
||||
|
||||
export function useHasMany(column: ColumnType) { |
||||
const { metas, getMeta } = useMetas() |
||||
const childMeta = computed<TableType>(() => { |
||||
return metas.value?.[(column.colOptions as any)?.fk_related_model_id as string] |
||||
}) |
||||
|
||||
const loadChildMeta = async () => { |
||||
await getMeta((column.colOptions as any)?.fk_related_model_id as string) |
||||
} |
||||
|
||||
const primaryValueProp = computed(() => { |
||||
return (childMeta?.value?.columns?.find((c) => c.pv) || childMeta?.value?.columns?.[0])?.title |
||||
}) |
||||
|
||||
return { childMeta, loadChildMeta, primaryValueProp } |
||||
} |
@ -0,0 +1,258 @@
|
||||
import type { ColumnType, LinkToAnotherRecordType, PaginatedType, TableType } from 'nocodb-sdk' |
||||
import type { Ref } from 'vue' |
||||
import { Modal, notification } from 'ant-design-vue' |
||||
import { useInjectionState, useMetas, useProject } from '#imports' |
||||
import { NOCO } from '~/lib' |
||||
import type { Row } from '~/composables' |
||||
import { extractSdkResponseErrorMsg } from '~/utils' |
||||
|
||||
interface DataApiResponse { |
||||
list: Record<string, any> |
||||
pageInfo: PaginatedType |
||||
} |
||||
|
||||
/** Store for managing Link to another cells */ |
||||
const [useProvideLTARStore, useLTARStore] = useInjectionState( |
||||
(column: Required<ColumnType>, row?: Ref<Row>, reloadData = () => {}) => { |
||||
// state
|
||||
const { metas, getMeta } = useMetas() |
||||
const { project } = useProject() |
||||
const { $api } = useNuxtApp() |
||||
const childrenExcludedList: Ref<DataApiResponse | undefined> = ref() |
||||
const childrenList: Ref<DataApiResponse | undefined> = ref() |
||||
const childrenExcludedListPagination = reactive({ |
||||
page: 1, |
||||
query: '', |
||||
size: 10, |
||||
}) |
||||
const childrenListPagination = reactive({ |
||||
page: 1, |
||||
query: '', |
||||
size: 10, |
||||
}) |
||||
|
||||
const colOptions = column.colOptions as LinkToAnotherRecordType |
||||
|
||||
// getters
|
||||
const meta = computed(() => metas?.value?.[column.fk_model_id as string]) |
||||
const relatedTableMeta = computed<TableType>(() => { |
||||
return metas.value?.[(column.colOptions as any)?.fk_related_model_id as string] |
||||
}) |
||||
|
||||
const rowId = computed(() => |
||||
meta.value.columns |
||||
.filter((c: Required<ColumnType>) => c.pk) |
||||
.map((c: Required<ColumnType>) => row?.value?.row?.[c.title]) |
||||
.join('___'), |
||||
) |
||||
|
||||
// actions
|
||||
const getRelatedTableRowId = (row: Record<string, any>) => { |
||||
return relatedTableMeta.value?.columns |
||||
?.filter((c) => c.pk) |
||||
.map((c) => row?.[c.title as string]) |
||||
.join('___') |
||||
} |
||||
|
||||
const loadRelatedTableMeta = async () => { |
||||
await getMeta(colOptions?.fk_related_model_id as string) |
||||
} |
||||
|
||||
const relatedTablePrimaryValueProp = computed(() => { |
||||
return (relatedTableMeta?.value?.columns?.find((c) => c.pv) || relatedTableMeta?.value?.columns?.[0])?.title |
||||
}) |
||||
const primaryValueProp = computed(() => { |
||||
return (meta?.value?.columns?.find((c: Required<ColumnType>) => c.pv) || relatedTableMeta?.value?.columns?.[0])?.title |
||||
}) |
||||
|
||||
const loadChildrenExcludedList = async () => { |
||||
try { |
||||
childrenExcludedList.value = await $api.dbTableRow.nestedChildrenExcludedList( |
||||
NOCO, |
||||
project.value.id as string, |
||||
meta.value.id, |
||||
rowId.value, |
||||
(column.colOptions as LinkToAnotherRecordType).type as 'mm' | 'hm', |
||||
column.title, |
||||
// todo: swagger type correction
|
||||
{ |
||||
limit: childrenExcludedListPagination.size, |
||||
offset: childrenExcludedListPagination.size * (childrenExcludedListPagination.page - 1), |
||||
where: |
||||
childrenExcludedListPagination.query && |
||||
`(${relatedTablePrimaryValueProp.value},like,${childrenExcludedListPagination.query})`, |
||||
} as any, |
||||
) |
||||
} catch (e: any) { |
||||
notification.error({ |
||||
message: 'Failed to load list', |
||||
description: await extractSdkResponseErrorMsg(e), |
||||
}) |
||||
} |
||||
} |
||||
|
||||
const loadChildrenList = async () => { |
||||
try { |
||||
childrenList.value = await $api.dbTableRow.nestedList( |
||||
NOCO, |
||||
project.value.id as string, |
||||
meta.value.id, |
||||
rowId.value, |
||||
colOptions.type as 'mm' | 'hm', |
||||
column.title, |
||||
// todo: swagger type correction
|
||||
{ |
||||
limit: childrenListPagination.size, |
||||
offset: childrenListPagination.size * (childrenListPagination.page - 1), |
||||
where: childrenListPagination.query && `(${relatedTablePrimaryValueProp.value},like,${childrenListPagination.query})`, |
||||
} as any, |
||||
) |
||||
} catch (e: any) { |
||||
notification.error({ |
||||
message: 'Failed to load children list', |
||||
description: await extractSdkResponseErrorMsg(e), |
||||
}) |
||||
} |
||||
} |
||||
|
||||
const deleteRelatedRow = async (row: Record<string, any>) => { |
||||
Modal.confirm({ |
||||
title: 'Do you want to delete the record?', |
||||
type: 'warning', |
||||
onOk: async () => { |
||||
const id = getRelatedTableRowId(row) |
||||
try { |
||||
$api.dbTableRow.delete(NOCO, project.value.id as string, relatedTableMeta.value.id as string, id as string) |
||||
reloadData?.() |
||||
await loadChildrenList() |
||||
} catch (e: any) { |
||||
notification.error({ |
||||
message: 'Delete failed', |
||||
description: await extractSdkResponseErrorMsg(e), |
||||
}) |
||||
} |
||||
}, |
||||
}) |
||||
} |
||||
|
||||
const unlink = async (row: Record<string, any>) => { |
||||
// const column = meta.columns.find(c => c.id === this.column.colOptions.fk_child_column_id);
|
||||
// todo: handle if new record
|
||||
// if (this.isNew) {
|
||||
// this.$emit('updateCol', this.row, _cn, null);
|
||||
// this.localState = null;
|
||||
// this.$emit('update:localState', this.localState);
|
||||
// return;
|
||||
// }
|
||||
// todo: handle bt column if required
|
||||
// if (column.rqd) {
|
||||
// this.$toast.info('Unlink is not possible, instead map to another parent.').goAway(3000);
|
||||
// return;
|
||||
// }
|
||||
try { |
||||
// todo: audit
|
||||
await $api.dbTableRow.nestedRemove( |
||||
NOCO, |
||||
project.value.title as string, |
||||
meta.value.title, |
||||
rowId.value, |
||||
colOptions.type as 'mm' | 'hm', |
||||
column.title, |
||||
getRelatedTableRowId(row) as string, |
||||
) |
||||
} catch (e) { |
||||
notification.error({ |
||||
message: 'Unlink failed', |
||||
description: await extractSdkResponseErrorMsg(e), |
||||
}) |
||||
} |
||||
reloadData?.() |
||||
// todo: reload table data and children list
|
||||
// this.$emit('loadTableData');
|
||||
// if (this.isForm && this.$refs.childList) {
|
||||
// this.$refs.childList.loadData();
|
||||
// }
|
||||
} |
||||
|
||||
const link = async (row: Record<string, any>) => { |
||||
// todo: handle new record
|
||||
// const pid = this._extractRowId(parent, this.parentMeta);
|
||||
// const id = this._extractRowId(this.row, this.meta);
|
||||
// const _cn = this.meta.columns.find(c => c.id === this.column.colOptions.fk_child_column_id).title;
|
||||
//
|
||||
// if (this.isNew) {
|
||||
// const _rcn = this.parentMeta.columns.find(c => c.id === this.column.colOptions.fk_parent_column_id).title;
|
||||
// this.localState = parent;
|
||||
// this.$emit('update:localState', this.localState);
|
||||
// this.$emit('updateCol', this.row, _cn, parent[_rcn]);
|
||||
// this.newRecordModal = false;
|
||||
// return;
|
||||
// }
|
||||
try { |
||||
await $api.dbTableRow.nestedAdd( |
||||
NOCO, |
||||
project.value.title as string, |
||||
meta.value.title as string, |
||||
rowId.value, |
||||
colOptions.type as 'mm' | 'hm', |
||||
column.title, |
||||
getRelatedTableRowId(row) as string, |
||||
) |
||||
} catch (e) { |
||||
notification.error({ |
||||
message: 'Linking failed', |
||||
description: await extractSdkResponseErrorMsg(e), |
||||
}) |
||||
} |
||||
|
||||
// todo: reload table data and child list
|
||||
// this.pid = pid;
|
||||
//
|
||||
// this.newRecordModal = false;
|
||||
//
|
||||
// this.$emit('loadTableData');
|
||||
// if (this.isForm && this.$refs.childList) {
|
||||
// this.$refs.childList.loadData();
|
||||
// }
|
||||
|
||||
reloadData?.() |
||||
} |
||||
|
||||
// watchers
|
||||
watch(childrenExcludedListPagination, async () => { |
||||
await loadChildrenExcludedList() |
||||
}) |
||||
watch(childrenListPagination, async () => { |
||||
await loadChildrenList() |
||||
}) |
||||
|
||||
return { |
||||
relatedTableMeta, |
||||
loadRelatedTableMeta, |
||||
relatedTablePrimaryValueProp, |
||||
childrenExcludedList, |
||||
childrenList, |
||||
rowId, |
||||
childrenExcludedListPagination, |
||||
childrenListPagination, |
||||
primaryValueProp, |
||||
meta, |
||||
unlink, |
||||
link, |
||||
loadChildrenExcludedList, |
||||
loadChildrenList, |
||||
row, |
||||
deleteRelatedRow, |
||||
getRelatedTableRowId, |
||||
} |
||||
}, |
||||
'ltar-store', |
||||
) |
||||
|
||||
export { useProvideLTARStore } |
||||
|
||||
export function useLTARStoreOrThrow() { |
||||
const ltarStore = useLTARStore() |
||||
if (ltarStore == null) throw new Error('Please call `useLTARStore` on the appropriate parent component') |
||||
return ltarStore |
||||
} |
@ -1,19 +0,0 @@
|
||||
import type { ColumnType, TableType } from 'nocodb-sdk' |
||||
import { useMetas } from './useMetas' |
||||
|
||||
export function useManyToMany(column: ColumnType) { |
||||
const { metas, getMeta } = useMetas() |
||||
const childMeta = computed<TableType>(() => { |
||||
return metas.value?.[(column.colOptions as any)?.fk_related_model_id as string] |
||||
}) |
||||
|
||||
const loadChildMeta = async () => { |
||||
await getMeta((column.colOptions as any)?.fk_related_model_id as string) |
||||
} |
||||
|
||||
const primaryValueProp = computed(() => { |
||||
return (childMeta?.value?.columns?.find((c) => c.pv) || childMeta?.value?.columns?.[0])?.title |
||||
}) |
||||
|
||||
return { childMeta, loadChildMeta, primaryValueProp } |
||||
} |
Loading…
Reference in new issue