Browse Source

feat: row height for grid view

Signed-off-by: mertmit <mertmit99@gmail.com>
pull/4840/head
mertmit 2 years ago
parent
commit
36fb93def5
  1. 5
      packages/nc-gui/components.d.ts
  2. 6
      packages/nc-gui/components/cell/MultiSelect.vue
  3. 29
      packages/nc-gui/components/cell/TextArea.vue
  4. 2
      packages/nc-gui/components/smartsheet/Toolbar.vue
  5. 70
      packages/nc-gui/components/smartsheet/toolbar/RowHeight.vue
  6. 19
      packages/nocodb-sdk/src/lib/Api.ts
  7. 11
      packages/nocodb/src/lib/meta/api/gridViewApis.ts
  8. 4
      packages/nocodb/src/lib/migrations/XcMigrationSourcev2.ts
  9. 16
      packages/nocodb/src/lib/migrations/v2/nc_025_add_row_height.ts
  10. 41
      packages/nocodb/src/lib/models/GridView.ts
  11. 41
      scripts/sdk/swagger.json

5
packages/nc-gui/components.d.ts vendored

@ -222,6 +222,10 @@ declare module '@vue/runtime-core' {
MdiScriptTextKeyOutline: typeof import('~icons/mdi/script-text-key-outline')['default']
MdiScriptTextOutline: typeof import('~icons/mdi/script-text-outline')['default']
MdiShieldKeyOutline: typeof import('~icons/mdi/shield-key-outline')['default']
MdiSizeL: typeof import('~icons/mdi/size-l')['default']
MdiSizeM: typeof import('~icons/mdi/size-m')['default']
MdiSizeS: typeof import('~icons/mdi/size-s')['default']
MdiSizeXl: typeof import('~icons/mdi/size-xl')['default']
MdiSlack: typeof import('~icons/mdi/slack')['default']
MdiSort: typeof import('~icons/mdi/sort')['default']
MdiSortAscending: typeof import('~icons/mdi/sort-ascending')['default']
@ -233,6 +237,7 @@ declare module '@vue/runtime-core' {
MdiTableColumnPlusAfter: typeof import('~icons/mdi/table-column-plus-after')['default']
MdiTableColumnPlusBefore: typeof import('~icons/mdi/table-column-plus-before')['default']
MdiTableLarge: typeof import('~icons/mdi/table-large')['default']
MdiTableRowHeight: typeof import('~icons/mdi/table-row-height')['default']
MdiText: typeof import('~icons/mdi/text')['default']
MdiThumbUp: typeof import('~icons/mdi/thumb-up')['default']
MdiTrashCan: typeof import('~icons/mdi/trash-can')['default']

6
packages/nc-gui/components/cell/MultiSelect.vue

@ -281,7 +281,7 @@ const onTagClick = (e: Event, onClose: Function) => {
v-model:value="vModel"
v-model:open="isOpen"
mode="multiple"
class="w-full"
class="w-full overflow-hidden"
:bordered="false"
clear-icon
show-search
@ -402,4 +402,8 @@ const onTagClick = (e: Event, onClose: Function) => {
:deep(.ant-select-selection-overflow-item) {
@apply "flex overflow-hidden";
}
:deep(.ant-select-selection-overflow) {
@apply flex-nowrap;
}
</style>

29
packages/nc-gui/components/cell/TextArea.vue

@ -1,6 +1,7 @@
<script setup lang="ts">
import type { GridType } from 'nocodb-sdk'
import type { VNodeRef } from '@vue/runtime-core'
import { EditModeInj, inject, useVModel } from '#imports'
import { ActiveViewInj, EditModeInj, inject, useVModel } from '#imports'
const props = defineProps<{
modelValue?: string | number
@ -10,9 +11,26 @@ const emits = defineEmits(['update:modelValue'])
const editEnabled = inject(EditModeInj)
const view = inject(ActiveViewInj, ref())
const vModel = useVModel(props, 'modelValue', emits, { defaultValue: '' })
const focus: VNodeRef = (el) => (el as HTMLTextAreaElement)?.focus()
const rowHeight = computed(() => {
if ((view.value?.view as GridType)?.row_height !== undefined) {
switch ((view.value?.view as GridType)?.row_height) {
case 0:
return 1
case 1:
return 2
case 2:
return 4
case 3:
return 6
}
}
})
</script>
<template>
@ -35,5 +53,14 @@ const focus: VNodeRef = (el) => (el as HTMLTextAreaElement)?.focus()
@mousedown.stop
/>
<a-textarea
v-else-if="rowHeight"
:key="rowHeight"
v-model:value="vModel"
class="w-full h-full"
:auto-size="{ minRows: rowHeight, maxRows: rowHeight }"
:bordered="false"
/>
<span v-else>{{ vModel }}</span>
</template>

2
packages/nc-gui/components/smartsheet/Toolbar.vue

@ -35,6 +35,8 @@ const { allowCSVDownload } = useSharedView()
<LazySmartsheetToolbarSortListMenu v-if="isGrid || isGallery || isKanban" />
<LazySmartsheetToolbarRowHeight v-if="isGrid" />
<LazySmartsheetToolbarShareView v-if="(isForm || isGrid || isKanban || isGallery) && !isPublic" />
<LazySmartsheetToolbarExport v-if="(!isPublic && !isUIAllowed('dataInsert')) || (isPublic && allowCSVDownload)" />

70
packages/nc-gui/components/smartsheet/toolbar/RowHeight.vue

@ -0,0 +1,70 @@
<script setup lang="ts">
import type { GridType } from 'nocodb-sdk'
import { ActiveViewInj, IsLockedInj, ReloadViewDataHookInj, inject, ref, useMenuCloseOnEsc } from '#imports'
const view = inject(ActiveViewInj, ref())
const isLocked = inject(IsLockedInj, ref(false))
const reloadDataHook = inject(ReloadViewDataHookInj)
const { $api } = useNuxtApp()
const open = ref(false)
const updateRowHeight = (rh: number) => {
if (view.value?.id) {
try {
$api.dbView.gridUpdate(view.value.id, {
row_height: rh,
})
;(view.value.view as GridType).row_height = rh
message.success('View updated successfully!')
reloadDataHook?.trigger()
open.value = false
} catch (e) {
message.error('There was an error while updating view!')
}
}
}
useMenuCloseOnEsc(open)
</script>
<template>
<a-dropdown v-model:visible="open" offset-y class="" :trigger="['click']" overlay-class-name="nc-dropdown-height-menu">
<div>
<a-button v-e="['c:row-height']" class="nc-height-menu-btn nc-toolbar-btn" :disabled="isLocked">
<div class="flex items-center gap-1">
<MdiTableRowHeight />
<!-- Row Height -->
<span class="text-capitalize !text-sm font-weight-normal">Row Height</span>
<MdiMenuDown class="text-grey" />
</div>
</a-button>
</div>
<template #overlay>
<div class="w-full bg-gray-50 shadow-lg menu-filter-dropdown !border" data-testid="nc-height-menu">
<div class="text-gray-500 !text-xs px-4 py-2">Select a row height</div>
<div class="flex flex-col w-full text-sm" @click.stop>
<div class="flex items-center py-1 px-2 hover:bg-gray-200" @click="updateRowHeight(0)">
<MdiSizeS class="text-xl mr-3" />Short
</div>
<div class="flex items-center py-1 px-2 hover:bg-gray-200" @click="updateRowHeight(1)">
<MdiSizeM class="text-xl mr-3" />Medium
</div>
<div class="flex items-center py-1 px-2 hover:bg-gray-200" @click="updateRowHeight(2)">
<MdiSizeL class="text-xl mr-3" />Tall
</div>
<div class="flex items-center py-1 px-2 hover:bg-gray-200" @click="updateRowHeight(3)">
<MdiSizeXl class="text-xl mr-3" />Extra
</div>
</div>
</div>
</template>
</a-dropdown>
</template>
<style scoped></style>

19
packages/nocodb-sdk/src/lib/Api.ts

@ -340,6 +340,7 @@ export interface GridType {
deleted?: boolean;
order?: number;
lock_type?: 'collaborative' | 'locked' | 'personal';
row_height?: number;
}
export interface GalleryType {
@ -2499,6 +2500,24 @@ export class Api<
...params,
}),
/**
* No description
*
* @tags DB view
* @name GridUpdate
* @request PATCH:/api/v1/db/meta/grids/{viewId}
* @response `200` `any` OK
*/
gridUpdate: (viewId: string, data: GridType, params: RequestParams = {}) =>
this.request<any, any>({
path: `/api/v1/db/meta/grids/${viewId}`,
method: 'PATCH',
body: data,
type: ContentType.Json,
format: 'json',
...params,
}),
/**
* No description
*

11
packages/nocodb/src/lib/meta/api/gridViewApis.ts

@ -12,6 +12,7 @@ import Project from '../../models/Project';
import View from '../../models/View';
import ncMetaAclMw from '../helpers/ncMetaAclMw';
import { metaApiMetrics } from '../helpers/apiMetrics';
import GridView from '../../models/GridView';
// @ts-ignore
export async function gridViewCreate(req: Request<any, any>, res) {
@ -25,10 +26,20 @@ export async function gridViewCreate(req: Request<any, any>, res) {
res.json(view);
}
export async function gridViewUpdate(req, res) {
Tele.emit('evt', { evt_type: 'view:updated', type: 'grid' });
res.json(await GridView.update(req.params.viewId, req.body));
}
const router = Router({ mergeParams: true });
router.post(
'/api/v1/db/meta/tables/:tableId/grids/',
metaApiMetrics,
ncMetaAclMw(gridViewCreate, 'gridViewCreate')
);
router.patch(
'/api/v1/db/meta/grids/:viewId',
metaApiMetrics,
ncMetaAclMw(gridViewUpdate, 'gridViewUpdate')
);
export default router;

4
packages/nocodb/src/lib/migrations/XcMigrationSourcev2.ts

@ -12,6 +12,7 @@ import * as nc_021_add_fields_in_token from './v2/nc_021_add_fields_in_token';
import * as nc_022_qr_code_column_type from './v2/nc_022_qr_code_column_type';
import * as nc_023_multiple_source from './v2/nc_023_multiple_source';
import * as nc_024_barcode_column_type from './v2/nc_024_barcode_column_type';
import * as nc_025_add_row_height from './v2/nc_025_add_row_height';
// Create a custom migration source class
export default class XcMigrationSourcev2 {
@ -35,6 +36,7 @@ export default class XcMigrationSourcev2 {
'nc_022_qr_code_column_type',
'nc_023_multiple_source',
'nc_024_barcode_column_type',
'nc_025_add_row_height',
]);
}
@ -72,6 +74,8 @@ export default class XcMigrationSourcev2 {
return nc_023_multiple_source;
case 'nc_024_barcode_column_type':
return nc_024_barcode_column_type;
case 'nc_025_add_row_height':
return nc_025_add_row_height;
}
}
}

16
packages/nocodb/src/lib/migrations/v2/nc_025_add_row_height.ts

@ -0,0 +1,16 @@
import { Knex } from 'knex';
import { MetaTable } from '../../utils/globals';
const up = async (knex: Knex) => {
await knex.schema.alterTable(MetaTable.GRID_VIEW, (table) => {
table.integer('row_height');
});
};
const down = async (knex) => {
await knex.schema.alterTable(MetaTable.GRID_VIEW, (table) => {
table.dropColumns('row_height');
});
};
export { up, down };

41
packages/nocodb/src/lib/models/GridView.ts

@ -5,18 +5,15 @@ import View from './View';
import NocoCache from '../cache/NocoCache';
export default class GridView {
title: string;
show: boolean;
is_default: boolean;
order: number;
fk_view_id: string;
columns?: GridViewColumn[];
project_id?: string;
base_id?: string;
meta?: string;
row_height?: number;
columns?: GridViewColumn[];
constructor(data: GridView) {
Object.assign(this, data);
}
@ -47,6 +44,7 @@ export default class GridView {
fk_view_id: view.fk_view_id,
project_id: view.project_id,
base_id: view.base_id,
row_height: view.row_height,
};
if (!(view.project_id && view.base_id)) {
const viewRef = await View.get(view.fk_view_id, ncMeta);
@ -63,4 +61,31 @@ export default class GridView {
const view = await this.get(id, ncMeta);
return view;
}
static async update(
viewId: string,
body: Partial<GridView>,
ncMeta = Noco.ncMeta
) {
// get existing cache
const key = `${CacheScope.GRID_VIEW}:${viewId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
o.row_height = body.row_height;
// set cache
await NocoCache.set(key, o);
}
// update meta
return await ncMeta.metaUpdate(
null,
null,
MetaTable.GRID_VIEW,
{
row_height: body.row_height,
},
{
fk_view_id: viewId,
}
);
}
}

41
scripts/sdk/swagger.json

@ -3024,6 +3024,44 @@
}
}
},
"/api/v1/db/meta/grids/{viewId}": {
"parameters": [
{
"schema": {
"type": "string"
},
"name": "viewId",
"in": "path",
"required": true
}
],
"patch": {
"summary": "",
"operationId": "db-view-grid-update",
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {}
}
}
}
},
"tags": [
"DB view"
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Grid"
}
}
}
}
}
},
"/api/v1/db/meta/grids/{gridId}/grid-columns": {
"parameters": [
{
@ -8508,6 +8546,9 @@
"locked",
"personal"
]
},
"row_height": {
"type": "number"
}
},
"description": ""

Loading…
Cancel
Save