Browse Source

fix issues from PR

pull/4749/head
flisowna 2 years ago
parent
commit
c2220c6a6b
  1. 10
      packages/nc-gui/components/cell/GeoData.vue
  2. 10
      packages/nc-gui/components/dlg/ViewCreate.vue
  3. 1
      packages/nc-gui/components/smartsheet/Gallery.vue
  4. 3
      packages/nc-gui/components/smartsheet/Kanban.vue
  5. 43
      packages/nc-gui/components/smartsheet/Map.vue
  6. 7
      packages/nc-gui/components/smartsheet/toolbar/MappedBy.vue
  7. 8
      packages/nc-gui/composables/useMapViewDataStore.ts
  8. 17
      packages/nc-gui/composables/useSmartsheetStore.ts
  9. 3
      packages/nc-gui/composables/useViewData.ts
  10. 1
      packages/nc-gui/context/index.ts
  11. 8
      packages/nc-gui/lang/en.json
  12. 3
      packages/nocodb/src/lib/migrations/v2/nc_025_map_view_column.ts
  13. 9
      packages/nocodb/src/lib/models/View.ts

10
packages/nc-gui/components/cell/GeoData.vue

@ -73,7 +73,7 @@ const onClickSetCurrentLocation = () => {
<a-button>{{ latLongStr }}</a-button> <a-button>{{ latLongStr }}</a-button>
<template #overlay> <template #overlay>
<a-form :model="formState" class="flex flex-col" @finish="handleFinish"> <a-form :model="formState" class="flex flex-col" @finish="handleFinish">
<a-form-item class="inputLat" label="Lat"> <a-form-item class="inputLat" :label="$t('labels.lat')">
<a-input <a-input
v-model:value="formState.latitude" v-model:value="formState.latitude"
type="number" type="number"
@ -91,7 +91,7 @@ const onClickSetCurrentLocation = () => {
/> />
</a-form-item> </a-form-item>
<a-form-item class="inputLng" label="Lng"> <a-form-item class="inputLng" :label="$t('labels.lng')">
<a-input <a-input
v-model:value="formState.longitude" v-model:value="formState.longitude"
type="number" type="number"
@ -111,12 +111,12 @@ const onClickSetCurrentLocation = () => {
<a-form-item> <a-form-item>
<div style="display: flex; align-items: center; margin-right: 0.5rem"> <div style="display: flex; align-items: center; margin-right: 0.5rem">
<MdiReload v-if="isLoading" :class="{ 'animate-infinite animate-spin text-gray-500': isLoading }" /> <MdiReload v-if="isLoading" :class="{ 'animate-infinite animate-spin text-gray-500': isLoading }" />
<a-button class="ml-2" @click="onClickSetCurrentLocation">Your Location</a-button> <a-button class="ml-2" @click="onClickSetCurrentLocation">{{ $t('labels.yourLocation') }}</a-button>
</div> </div>
</a-form-item> </a-form-item>
<a-form-item class="buttons"> <a-form-item class="buttons">
<a-button type="text" @click="clear">Cancel</a-button> <a-button type="text" @click="clear">{{ $t('general.cancel') }}</a-button>
<a-button type="primary" html-type="submit">Submit</a-button> <a-button type="primary" html-type="submit">{{ $t('general.submit') }}</a-button>
</a-form-item> </a-form-item>
</a-form> </a-form>
</template> </template>

10
packages/nc-gui/components/dlg/ViewCreate.vue

@ -83,15 +83,9 @@ const viewNameRules = [
}, },
] ]
const groupingFieldColumnRules = [ const groupingFieldColumnRules = [{ required: true, message: `${t('general.groupingField')} ${t('general.required')}` }]
// name is required
{ required: true, message: `${t('general.groupingField')} ${t('general.required')}` },
]
const geoDataFieldColumnRules = [ const geoDataFieldColumnRules = [{ required: true, message: `${t('general.geoDataField')} ${t('general.required')}` }]
// name is required
{ required: true, message: `${t('general.geoDataField')} ${t('general.required')}` },
]
const typeAlias = computed( const typeAlias = computed(
() => () =>

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

@ -105,7 +105,6 @@ const expandForm = (row: RowType, state?: Record<string, any>) => {
expandedFormRow.value = row expandedFormRow.value = row
expandedFormRowState.value = state expandedFormRowState.value = state
expandedFormDlg.value = true expandedFormDlg.value = true
console.log(state)
} }
} }

3
packages/nc-gui/components/smartsheet/Kanban.vue

@ -12,7 +12,6 @@ import {
IsPublicInj, IsPublicInj,
MetaInj, MetaInj,
OpenNewRecordFormHookInj, OpenNewRecordFormHookInj,
ReadonlyInj,
inject, inject,
onBeforeMount, onBeforeMount,
onBeforeUnmount, onBeforeUnmount,
@ -85,8 +84,6 @@ provide(IsGridInj, ref(false))
provide(IsKanbanInj, ref(true)) provide(IsKanbanInj, ref(true))
provide(ReadonlyInj, !isUIAllowed('xcDatatableEditable'))
const hasEditPermission = $computed(() => isUIAllowed('xcDatatableEditable')) const hasEditPermission = $computed(() => isUIAllowed('xcDatatableEditable'))
const fields = inject(FieldsInj, ref([])) const fields = inject(FieldsInj, ref([]))

43
packages/nc-gui/components/smartsheet/Map.vue

@ -3,35 +3,44 @@ import 'leaflet/dist/leaflet.css'
import L, { LatLng } from 'leaflet' import L, { LatLng } from 'leaflet'
import 'leaflet.markercluster' import 'leaflet.markercluster'
import { ViewTypes } from 'nocodb-sdk' import { ViewTypes } from 'nocodb-sdk'
// import contextmenu from 'vue3-contextmenu'
// import 'vue3-contextmenu/dist/vue3-contextmenu.css'
import { IsGalleryInj, IsGridInj, IsMapInj, OpenNewRecordFormHookInj, onMounted, provide, ref } from '#imports' import { IsGalleryInj, IsGridInj, IsMapInj, OpenNewRecordFormHookInj, onMounted, provide, ref } from '#imports'
import type { Row as RowType } from '~/lib' import type { Row as RowType } from '~/lib'
import { latLongToJoinedString } from '~~/utils/geoDataUtils' import { latLongToJoinedString } from '~~/utils/geoDataUtils'
provide(IsGalleryInj, ref(false)) provide(IsGalleryInj, ref(false))
provide(IsGridInj, ref(false)) provide(IsGridInj, ref(false))
provide(IsMapInj, ref(true)) provide(IsMapInj, ref(true))
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
const reloadViewDataHook = inject(ReloadViewDataHookInj) const reloadViewDataHook = inject(ReloadViewDataHookInj)
const reloadViewMetaHook = inject(ReloadViewMetaHookInj) const reloadViewMetaHook = inject(ReloadViewMetaHookInj)
const { formattedData, loadMapData, loadMapMeta, mapMetaData, geoDataFieldColumn, addEmptyRow, syncCount, paginationData } = const { formattedData, loadMapData, loadMapMeta, mapMetaData, geoDataFieldColumn, addEmptyRow, syncCount, paginationData } =
useMapViewStoreOrThrow() useMapViewStoreOrThrow()
const markersClusterGroupRef = ref<L.MarkerClusterGroup>() const markersClusterGroupRef = ref<L.MarkerClusterGroup>()
const mapContainerRef = ref<HTMLElement>() const mapContainerRef = ref<HTMLElement>()
const myMapRef = ref<L.Map>() const myMapRef = ref<L.Map>()
const meta = inject(MetaInj, ref()) const meta = inject(MetaInj, ref())
const view = inject(ActiveViewInj, ref()) const view = inject(ActiveViewInj, ref())
const openNewRecordFormHook = inject(OpenNewRecordFormHookInj, createEventHook()) const openNewRecordFormHook = inject(OpenNewRecordFormHookInj, createEventHook())
const expandedFormDlg = ref(false) const expandedFormDlg = ref(false)
const expandedFormRow = ref<RowType>() const expandedFormRow = ref<RowType>()
const expandedFormRowState = ref<Record<string, any>>() const expandedFormRowState = ref<Record<string, any>>()
const expandedFormClickedLatLongForNewRow = ref<[number, number]>()
const fallBackCenterLocation = { const fallBackCenterLocation = {
lat: 51, lat: 51,
@ -39,11 +48,11 @@ const fallBackCenterLocation = {
} }
const getMapZoomLocalStorageKey = (viewId: string) => { const getMapZoomLocalStorageKey = (viewId: string) => {
return `mapView.zoom.${viewId}` return `mapView.${viewId}.zoom`
} }
const getMapCenterLocalStorageKey = (viewId: string) => `mapView.center.${viewId}` const getMapCenterLocalStorageKey = (viewId: string) => `mapView.${viewId}.center`
const expandForm = (row: RowType, state?: Record<string, any>, clickedLatLongForNewRow?: [number, number]) => { const expandForm = (row: RowType, state?: Record<string, any>) => {
const rowId = extractPkFromRow(row.row, meta.value!.columns!) const rowId = extractPkFromRow(row.row, meta.value!.columns!)
if (rowId) { if (rowId) {
router.push({ router.push({
@ -53,13 +62,9 @@ const expandForm = (row: RowType, state?: Record<string, any>, clickedLatLongFor
}, },
}) })
} else { } else {
expandedFormClickedLatLongForNewRow.value = clickedLatLongForNewRow
expandedFormRow.value = row expandedFormRow.value = row
expandedFormRowState.value = state expandedFormRowState.value = state
expandedFormDlg.value = true expandedFormDlg.value = true
// const lat = state?.lat
// const lng = state?.lng
} }
} }
@ -85,7 +90,7 @@ const expandedFormOnRowIdDlg = computed({
const addMarker = (lat: number, long: number, row: RowType) => { const addMarker = (lat: number, long: number, row: RowType) => {
if (markersClusterGroupRef.value == null) { if (markersClusterGroupRef.value == null) {
throw new Error('Map is null') throw new Error('Marker cluster is null')
} }
const newMarker = L.marker([lat, long]).on('click', () => { const newMarker = L.marker([lat, long]).on('click', () => {
expandForm(row) expandForm(row)
@ -98,7 +103,6 @@ const resetZoomAndCenterBasedOnLocalStorage = () => {
return return
} }
const initialZoomLevel = parseInt(localStorage.getItem(getMapZoomLocalStorageKey(mapMetaData.value.fk_view_id)) || '10') const initialZoomLevel = parseInt(localStorage.getItem(getMapZoomLocalStorageKey(mapMetaData.value.fk_view_id)) || '10')
const initialCenterLocalStorageStr = localStorage.getItem(getMapCenterLocalStorageKey(mapMetaData.value.fk_view_id)) const initialCenterLocalStorageStr = localStorage.getItem(getMapCenterLocalStorageKey(mapMetaData.value.fk_view_id))
const initialCenter = initialCenterLocalStorageStr ? JSON.parse(initialCenterLocalStorageStr) : fallBackCenterLocation const initialCenter = initialCenterLocalStorageStr ? JSON.parse(initialCenterLocalStorageStr) : fallBackCenterLocation
@ -142,13 +146,12 @@ onMounted(async () => {
}) })
myMap.on('contextmenu', async function (e) { myMap.on('contextmenu', async function (e) {
const lat = e.latlng.lat const { lat, lng } = e.latlng
const lng = e.latlng.lng
const newRow = await addEmptyRow() const newRow = await addEmptyRow()
if (geoDataFieldColumn.value?.title) { if (geoDataFieldColumn.value?.title) {
newRow.row[geoDataFieldColumn.value.title] = latLongToJoinedString(lat, lng) newRow.row[geoDataFieldColumn.value.title] = latLongToJoinedString(lat, lng)
} }
expandForm(newRow, [lat, lng]) expandForm(newRow)
}) })
}) })
@ -205,13 +208,13 @@ const count = computed(() => paginationData.value.totalRows)
<div id="mapContainer" ref="mapContainerRef"> <div id="mapContainer" ref="mapContainerRef">
<a-tooltip placement="bottom" class="tooltip"> <a-tooltip placement="bottom" class="tooltip">
<template #title> <template #title>
<span v-if="count > 1000"> You're over the limit. </span> <span v-if="count > 1000"> {{ $t('msg.info.map.overLimit') }} </span>
<span v-else> You're getting close to the limit. </span> <span v-else-if="count > 900"> {{ $t('msg.info.map.closeLimit') }} </span>
<span> The limit of markers shown in a Map View is 1000 records. </span> <span> {{ $t('msg.info.map.limitNumber') }} </span>
</template> </template>
<div v-if="count > 900" class="nc-warning-info flex min-w-32px h-32px items-center gap-1 px-2 bg-white"> <div v-if="count > 900" class="nc-warning-info flex min-w-32px h-32px items-center gap-1 px-2 bg-white">
<div>{{ count }} records</div> <div>{{ count }} {{ $t('objects.records') }}</div>
<mdi-map-marker-alert /> <mdi-map-marker-alert />
</div> </div>
</a-tooltip> </a-tooltip>

7
packages/nc-gui/components/smartsheet/toolbar/MappedBy.vue

@ -72,12 +72,7 @@ const handleChange = () => {
</script> </script>
<template> <template>
<a-dropdown <a-dropdown v-if="!IsPublic" v-model:visible="stackedByDropdown" :trigger="['click']">
v-if="!IsPublic"
v-model:visible="stackedByDropdown"
:trigger="['click']"
overlay-class-name="nc-dropdown-kanban-stacked-by-menu"
>
<div class="nc-kanban-btn"> <div class="nc-kanban-btn">
<a-button <a-button
v-e="['c:kanban:change-grouping-field']" v-e="['c:kanban:change-grouping-field']"

8
packages/nc-gui/composables/useMapViewDataStore.ts

@ -7,11 +7,14 @@ import type { Row } from '~/lib'
export const geodataToggleState = reactive({ show: false }) export const geodataToggleState = reactive({ show: false })
const formatData = (list: Record<string, any>[]) => const formatData = (list: Record<string, any>[]) =>
list.map((row) => ({ list.map(
(row) =>
({
row: { ...row }, row: { ...row },
oldRow: { ...row }, oldRow: { ...row },
rowMeta: {}, rowMeta: {},
})) } as Row),
)
const [useProvideMapViewStore, useMapViewStore] = useInjectionState( const [useProvideMapViewStore, useMapViewStore] = useInjectionState(
( (
@ -73,7 +76,6 @@ const [useProvideMapViewStore, useMapViewStore] = useInjectionState(
} }
async function loadMapData() { async function loadMapData() {
if ((!project?.value?.id || !meta.value?.id || !viewMeta.value?.id) && !isPublic?.value) return if ((!project?.value?.id || !meta.value?.id || !viewMeta.value?.id) && !isPublic?.value) return
const res = !isPublic.value const res = !isPublic.value

17
packages/nc-gui/composables/useSmartsheetStore.ts

@ -12,23 +12,9 @@ const [useProvideSmartsheetStore, useSmartsheetStore] = useInjectionState(
initialSorts?: Ref<SortType[]>, initialSorts?: Ref<SortType[]>,
initialFilters?: Ref<FilterType[]>, initialFilters?: Ref<FilterType[]>,
) => { ) => {
// const paginatedData = inject(PaginationDataInj)!
// const { paginationData } = useViewData(meta, view)
// debugger
const { $api } = useNuxtApp() const { $api } = useNuxtApp()
const { sqlUis, project } = useProject() const { sqlUis, project } = useProject()
const totalNumberOfTableRows = ref(async () => {
const { count } = await $api.dbViewRow.count(
NOCO,
project?.value?.title as string,
meta?.value?.id as string,
meta?.value?.id as string,
)
return count
})
const sqlUi = ref(meta.value?.base_id ? sqlUis.value[meta.value?.base_id] : Object.values(sqlUis.value)[0]) const sqlUi = ref(meta.value?.base_id ? sqlUis.value[meta.value?.base_id] : Object.values(sqlUis.value)[0])
const cellRefs = ref<HTMLTableDataCellElement[]>([]) const cellRefs = ref<HTMLTableDataCellElement[]>([])
@ -37,8 +23,6 @@ const [useProvideSmartsheetStore, useSmartsheetStore] = useInjectionState(
const eventBus = useEventBus<SmartsheetStoreEvents>(Symbol('SmartsheetStore')) const eventBus = useEventBus<SmartsheetStoreEvents>(Symbol('SmartsheetStore'))
// getters
// const count = computed(() => paginatedData.value?.totalRows ?? Infinity)
const isLocked = computed(() => view.value?.lock_type === 'locked') const isLocked = computed(() => view.value?.lock_type === 'locked')
const isPkAvail = computed(() => (meta.value as TableType)?.columns?.some((c) => c.pk)) const isPkAvail = computed(() => (meta.value as TableType)?.columns?.some((c) => c.pk))
const isGrid = computed(() => view.value?.type === ViewTypes.GRID) const isGrid = computed(() => view.value?.type === ViewTypes.GRID)
@ -68,7 +52,6 @@ const [useProvideSmartsheetStore, useSmartsheetStore] = useInjectionState(
const nestedFilters = ref<FilterType[]>(unref(initialFilters) ?? []) const nestedFilters = ref<FilterType[]>(unref(initialFilters) ?? [])
return { return {
totalNumberOfTableRows,
view, view,
meta, meta,
isLocked, isLocked,

3
packages/nc-gui/composables/useViewData.ts

@ -209,7 +209,6 @@ export function useViewData(
async function insertRow( async function insertRow(
currentRow: Row, currentRow: Row,
_rowIndex = formattedData.value?.length,
ltarState: Record<string, any> = {}, ltarState: Record<string, any> = {},
{ metaValue = meta.value, viewMetaValue = viewMeta.value }: { metaValue?: TableType; viewMetaValue?: ViewType } = {}, { metaValue = meta.value, viewMetaValue = viewMeta.value }: { metaValue?: TableType; viewMetaValue?: ViewType } = {},
) { ) {
@ -323,7 +322,7 @@ export function useViewData(
await until(() => !(row.rowMeta?.new && row.rowMeta?.saving)).toMatch((v) => v) await until(() => !(row.rowMeta?.new && row.rowMeta?.saving)).toMatch((v) => v)
if (row.rowMeta.new) { if (row.rowMeta.new) {
return await insertRow(row, formattedData.value.indexOf(row), ltarState, args) return await insertRow(row, ltarState, args)
} else { } else {
// if the field name is missing skip update // if the field name is missing skip update
if (property) { if (property) {

1
packages/nc-gui/context/index.ts

@ -17,7 +17,6 @@ export const IsFormInj: InjectionKey<Ref<boolean>> = Symbol('is-form-injection')
export const IsGridInj: InjectionKey<Ref<boolean>> = Symbol('is-grid-injection') export const IsGridInj: InjectionKey<Ref<boolean>> = Symbol('is-grid-injection')
export const IsGalleryInj: InjectionKey<Ref<boolean>> = Symbol('is-gallery-injection') export const IsGalleryInj: InjectionKey<Ref<boolean>> = Symbol('is-gallery-injection')
export const IsMapInj: InjectionKey<Ref<boolean>> = Symbol('is-map-injection') export const IsMapInj: InjectionKey<Ref<boolean>> = Symbol('is-map-injection')
export const IsGeodataActiveInj: InjectionKey<Ref<boolean>> = Symbol('is-geodata-active-injection')
export const IsKanbanInj: InjectionKey<Ref<boolean>> = Symbol('is-kanban-injection') export const IsKanbanInj: InjectionKey<Ref<boolean>> = Symbol('is-kanban-injection')
export const IsLockedInj: InjectionKey<Ref<boolean>> = Symbol('is-locked-injection') export const IsLockedInj: InjectionKey<Ref<boolean>> = Symbol('is-locked-injection')
export const CellValueInj: InjectionKey<Ref<any>> = Symbol('cell-value-injection') export const CellValueInj: InjectionKey<Ref<any>> = Symbol('cell-value-injection')

8
packages/nc-gui/lang/en.json

@ -250,6 +250,9 @@
"barcodeFormat": "Barcode format", "barcodeFormat": "Barcode format",
"qrCodeValueTooLong": "Too many characters for a QR code", "qrCodeValueTooLong": "Too many characters for a QR code",
"barcodeValueTooLong": "Too many characters for a barcode", "barcodeValueTooLong": "Too many characters for a barcode",
"yourLocation": "Your Location",
"lng": "Lng",
"lat": "Lat",
"aggregateFunction": "Aggregate function", "aggregateFunction": "Aggregate function",
"dbCreateIfNotExists": "Database : create if not exists", "dbCreateIfNotExists": "Database : create if not exists",
"clientKey": "Client Key", "clientKey": "Client Key",
@ -515,6 +518,11 @@
"orgCreator": "Creator can create new projects and access any invited project.", "orgCreator": "Creator can create new projects and access any invited project.",
"orgViewer": "Viewer is not allowed to create new projects but they can access any invited project." "orgViewer": "Viewer is not allowed to create new projects but they can access any invited project."
}, },
"map": {
"overLimit": "You're over the limit.",
"closeLimit": "You're getting close to the limit.",
"limitNumber": "The limit of markers shown in a Map View is 1000 records."
},
"footerInfo": "Rows per page", "footerInfo": "Rows per page",
"upload": "Select file to Upload", "upload": "Select file to Upload",
"upload_sub": "or drag and drop file", "upload_sub": "or drag and drop file",

3
packages/nocodb/src/lib/migrations/v2/nc_025_map_view_column.ts

@ -5,9 +5,7 @@ const up = async (knex) => {
table.string('id', 20).primary().notNullable(); table.string('id', 20).primary().notNullable();
table.string('base_id', 20); table.string('base_id', 20);
// table.foreign('base_id').references(`${MetaTable.BASES}.id`);
table.string('project_id', 128); table.string('project_id', 128);
// table.foreign('project_id').references(`${MetaTable.PROJECT}.id`);
table.string('fk_view_id', 20); table.string('fk_view_id', 20);
table.foreign('fk_view_id').references(`${MetaTable.MAP_VIEW}.fk_view_id`); table.foreign('fk_view_id').references(`${MetaTable.MAP_VIEW}.fk_view_id`);
@ -16,7 +14,6 @@ const up = async (knex) => {
table.string('uuid'); table.string('uuid');
// todo: type
table.string('label'); table.string('label');
table.string('help'); table.string('help');

9
packages/nocodb/src/lib/models/View.ts

@ -433,7 +433,7 @@ export default class View implements ViewType {
show = false; show = false;
} }
} }
// TODO: Check whether/what we need to do here for properly integrate MapView
else if (view.type === ViewTypes.KANBAN && !copyFromView) { else if (view.type === ViewTypes.KANBAN && !copyFromView) {
const kanbanView = await KanbanView.get(view_id, ncMeta); const kanbanView = await KanbanView.get(view_id, ncMeta);
if (vCol.id === kanbanView?.fk_grp_col_id) { if (vCol.id === kanbanView?.fk_grp_col_id) {
@ -453,6 +453,13 @@ export default class View implements ViewType {
} }
} }
else if (view.type === ViewTypes.MAP && !copyFromView) {
const mapView = await MapView.get(view_id, ncMeta);
if (vCol.id === mapView?.fk_geo_data_col_id) {
show = true;
}
}
// if columns is list of virtual columns then get the parent column // if columns is list of virtual columns then get the parent column
const col = vCol.fk_column_id const col = vCol.fk_column_id
? await Column.get({ colId: vCol.fk_column_id }, ncMeta) ? await Column.get({ colId: vCol.fk_column_id }, ncMeta)

Loading…
Cancel
Save