Browse Source

refactor: shared grid view api corrections

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/1668/head
Pranav C 3 years ago
parent
commit
ae2703e93d
  1. 7
      packages/nc-gui/components/project/appStore.vue
  2. 155
      packages/nc-gui/components/project/spreadsheet/public/xcTable.vue
  3. 27
      packages/nocodb-sdk/src/lib/Api.ts
  4. 5
      packages/nocodb/src/lib/noco/meta/api/dataApis/dataApis.ts
  5. 78
      packages/nocodb/src/lib/noco/meta/api/publicApis/publicDataApis.ts
  6. 2
      packages/nocodb/src/lib/noco/meta/api/publicApis/publicDataExportApis.ts
  7. 10
      packages/nocodb/src/lib/noco/meta/api/publicApis/publicMetaApis.ts
  8. 72
      scripts/sdk/swagger.json

7
packages/nc-gui/components/project/appStore.vue

@ -213,15 +213,8 @@ export default {
},
async created() {
await this.loadPluginList()
this.readPluginDefaults()
},
methods: {
async readPluginDefaults() {
try {
this.defaultConfig = await this.$store.dispatch('sqlMgr/ActSqlOp', [null, 'xcPluginDemoDefaults'])
} catch (e) {
}
},
async confirmResetPlugin() {
try {
await this.$api.plugin.update(this.resetPluginRef.id, {

155
packages/nc-gui/components/project/spreadsheet/public/xcTable.vue

@ -22,74 +22,7 @@
class="nc-table-toolbar elevation-0 xc-toolbar xc-border-bottom"
style="z-index: 7;border-radius: 4px"
>
<!--
<div class="d-flex xc-border align-center search-box" style="min-width:156px">
<v-menu bottom offset-y>
<template #activator="{on}">
<div style="min-width: 56px" v-on="on">
<v-icon
class="ml-2"
small
color="grey"
>
mdi-magnify
</v-icon>
<v-icon
color="grey"
class="pl-0 pa-1"
small
>
mdi-menu-down
</v-icon>
</div>
</template>
<v-list dense>
<v-list-item
v-for="col in meta.columns"
:key="col.title"
@click="searchField = col.title"
>
<span class="caption">{{ col.title }}</span>
</v-list-item>
</v-list>
</v-menu>
<v-divider
vertical
/>
<v-text-field
v-model="searchQuery"
autocomplete="off"
style="min-width: 100px ; width: 150px"
flat
dense
solo
hide-details
:placeholder="searchField ? `Search '${searchField}' column` : 'Search all columns'"
class="elevation-0 pa-0 flex-grow-1 caption search-field"
@keyup.enter="loadTableData"
@blur="loadTableData"
/>
</div>
<span
v-if="relationType && false"
class="caption grey&#45;&#45;text"
>{{ refTable }}({{
relationPrimaryValue
}}) -> {{ relationType === 'hm' ? ' Has Many ' : ' Belongs To ' }} -> {{ table }}</span>
-->
<div class="d-inline-flex">
<!-- <v-btn outlined small text @click="reload">
<v-icon small class="mr-1" color="grey darken-3">
mdi-reload
</v-icon>
Reload
</v-btn>-->
<fields-menu
v-model="showFields"
:field-list="fieldList"
@ -123,32 +56,6 @@
/>
</div>
<v-spacer class="h-100" @dblclick="debug=true" />
<!-- <v-menu>
<template #activator="{ on, attrs }">
<v-icon
v-bind="attrs"
small
class="mx-2"
color="grey darken-3"
v-on="on"
>
mdi-arrow-collapse-vertical
</v-icon>
</template>
<v-list dense class="caption">
<v-list-item v-for="h in cellHeights" :key="h.size" dense @click.stop="cellHeight = h.size">
<v-list-item-icon class="mr-1">
<v-icon small :color="cellHeight === h.size && 'primary'">
{{ h.icon }}
</v-icon>
</v-list-item-icon>
<v-list-item-title :class="{'primary&#45;&#45;text' : cellHeight === h.size}" style="text-transform: capitalize">
{{ h.size }}
</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>-->
</v-toolbar>
<div
@ -185,9 +92,6 @@
color="primary lighten-2"
@input="loadTableData"
/>
<!-- <div v-else class="d-flex justify-center py-4">-->
<!-- <v-alert type="info" dense class="ma-1 flex-shrink-1">Table is empty</v-alert>-->
<!-- </div>-->
</div>
</div>
</template>
@ -223,14 +127,12 @@
import { ErrorMessages } from 'nocodb-sdk'
import spreadsheet from '../mixins/spreadsheet'
import ApiFactory from '../apis/apiFactory'
// import EditableCell from "../editableCell";
import FieldsMenu from '../components/fieldsMenu'
import SortListMenu from '../components/sortListMenu'
import ColumnFilterMenu from '../components/columnFilterMenu'
import XcGridView from '../views/xcGridView'
import { SqlUI } from '@/helpers/sqlUi'
import CsvExportImport from '~/components/project/spreadsheet/components/moreActions'
// import ExpandedForm from "../expandedForm";
export default {
name: 'XcTable',
@ -369,23 +271,6 @@ export default {
edited() {
return this.data && this.data.some(r => r.rowMeta && (r.rowMeta.new || r.rowMeta.changed))
},
// hasMany() {
// return this.meta && this.meta.hasMany
// ? this.meta.hasMany.reduce((hm, o) => {
// hm[o.rcn] = hm[o.rcn] || []
// hm[o.rcn].push(o)
// return hm
// }, {})
// : {}
// },
// belongsTo() {
// return this.meta && this.meta.belongsTo
// ? this.meta.belongsTo.reduce((bt, o) => {
// bt[o.title] = o
// return bt
// }, {})
// : {}
// },
table() {
if (this.relationType === 'hm') {
return this.relation.table_name
@ -426,21 +311,6 @@ export default {
this.searchField = this.primaryValueColumn
},
created() {
/* if (this.relationType === 'hm') {
this.filters.push({
field: this.relation.column_name,
op: 'is equal',
value: this.relationIdValue,
readOnly: true
})
} else if (this.relationType === 'bt') {
this.filters.push({
field: this.relation.rcn,
op: 'is equal',
value: this.relationIdValue,
readOnly: true
})
} */
document.addEventListener('keydown', this.onKeyDown)
},
beforeDestroy() {
@ -519,7 +389,9 @@ export default {
this.loading = true
try {
this.viewMeta = (await this.$api.public.sharedViewMetaGet(this.$route.params.id, {
password: this.password
headers: {
'xc-password': this.password
}
}))
this.meta = this.viewMeta.model
this.metas = this.viewMeta.relatedMetas
@ -547,26 +419,21 @@ export default {
list,
pageInfo: { totalRows: count }
}
} = (await this.$api.public.dataList(this.$route.params.id, {
password: this.password,
sorts: this.sorts && this.sorts.map(({
} = (await this.$api.public.dataList(this.$route.params.id, {}, {
sortArrJson: JSON.stringify(this.sorts && this.sorts.map(({
fk_column_id,
direction
}) => ({
direction,
fk_column_id
})),
filters: this.filters
}, this.queryParams
}))),
filterArrJson: JSON.stringify(this.filters),
...this.queryParams
}, {
headers: { password: this.password }
}
))
// this.client = client
// this.showFields = queryParams && queryParams.showFields
// this.meta = meta
// eslint-disable-next-line camelcase
// this.modelName = model_name
this.count = count
this.data = list.map(row => ({
row,

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

@ -2843,16 +2843,10 @@ export class Api<
* @request POST:/api/v1/db/public/shared-view/{sharedViewUuid}/rows
* @response `200` `any` OK
*/
sharedViewCreate: (
sharedViewUuid: string,
data: { data?: any; password?: string },
params: RequestParams = {}
) =>
sharedViewCreate: (sharedViewUuid: string, params: RequestParams = {}) =>
this.request<any, any>({
path: `/api/v1/db/public/shared-view/${sharedViewUuid}/rows`,
method: 'POST',
body: data,
type: ContentType.FormData,
format: 'json',
...params,
}),
@ -2941,7 +2935,6 @@ export class Api<
dataRelationList: (
sharedViewUuid: string,
columnName: string,
data: { password?: string },
query?: { limit?: string; offset?: string },
params: RequestParams = {}
) =>
@ -2949,8 +2942,6 @@ export class Api<
path: `/api/v1/db/public/shared-view/${sharedViewUuid}/rows/nested/${columnName}`,
method: 'POST',
query: query,
body: data,
type: ContentType.Json,
format: 'json',
...params,
}),
@ -2960,19 +2951,13 @@ export class Api<
*
* @tags Public
* @name SharedViewMetaGet
* @request POST:/api/v1/db/public/shared-view/{sharedViewUuid}/meta
* @request GET:/api/v1/db/public/shared-view/{sharedViewUuid}/meta
* @response `200` `object` OK
*/
sharedViewMetaGet: (
sharedViewUuid: string,
data: { password?: string },
params: RequestParams = {}
) =>
sharedViewMetaGet: (sharedViewUuid: string, params: RequestParams = {}) =>
this.request<object, any>({
path: `/api/v1/db/public/shared-view/${sharedViewUuid}/meta`,
method: 'POST',
body: data,
type: ContentType.Json,
method: 'GET',
format: 'json',
...params,
}),
@ -3066,7 +3051,7 @@ export class Api<
*
* @tags Utils
* @name CommentCount
* @request GET:/api/v1/db/meta/meta/audits/comments/count
* @request GET:/api/v1/db/meta/audits/comments/count
* @response `201` `any` Created
*/
commentCount: (
@ -3074,7 +3059,7 @@ export class Api<
params: RequestParams = {}
) =>
this.request<any, any>({
path: `/api/v1/db/meta/meta/audits/comments/count`,
path: `/api/v1/db/meta/audits/comments/count`,
method: 'GET',
query: query,
format: 'json',

5
packages/nocodb/src/lib/noco/meta/api/dataApis/dataApis.ts

@ -20,11 +20,6 @@ export async function dataList(req: Request, res: Response, next) {
res.json(await getDataList(model, view, req));
}
// async function dataListNew(req: Request, res: Response) {
// const { model, view } = await getViewAndModelFromRequest(req);
// res.json(await getDataList(model, view, req));
// }
export async function mmList(req: Request, res: Response, next) {
const view = await View.get(req.params.viewId);

78
packages/nocodb/src/lib/noco/meta/api/publicApis/publicDataApis.ts

@ -18,12 +18,12 @@ import slash from 'slash';
export async function dataList(req: Request, res: Response) {
try {
const view = await View.getByUUID(req.params.publicDataUuid);
const view = await View.getByUUID(req.params.sharedViewUuid);
if (!view) NcError.notFound('Not found');
if (view.type !== ViewTypes.GRID) NcError.notFound('Not found');
if (view.password && view.password !== req.body?.password) {
if (view.password && view.password !== req.headers?.['xc-password']) {
return NcError.forbidden(ErrorMessages.INVALID_SHARED_VIEW_PASSWORD);
}
@ -39,37 +39,22 @@ export async function dataList(req: Request, res: Response) {
dbDriver: NcConnectionMgrv2.get(base)
});
const key = `${model.title}List`;
const requestObj = {
[key]: await baseModel.defaultResolverReq(req.query)
};
const data = (
await nocoExecute(
requestObj,
{
[key]: async args => {
return await baseModel.list(args);
}
},
{},
{
nested: {
[key]: {
...req.query,
sortArr: req.body?.sorts,
filterArr: req.body?.filters
}
}
}
)
)?.[key];
const listArgs: any = { ...req.query };
try {
listArgs.filterArr = JSON.parse(listArgs.filterArrJson);
} catch (e) {}
try {
listArgs.sortArr = JSON.parse(listArgs.sortArrJson);
} catch (e) {}
const data = await nocoExecute(
await baseModel.defaultResolverReq(req.query),
await baseModel.list(listArgs),
{},
listArgs
);
const count = await baseModel.count({
...req.query,
filterArr: req.body?.filters
});
const count = await baseModel.count(listArgs);
res.json({
data: new PagedResponseImpl(data, { ...req.query, count })
@ -85,12 +70,12 @@ async function dataInsert(
res: Response,
next
) {
const view = await View.getByUUID(req.params.publicDataUuid);
const view = await View.getByUUID(req.params.sharedViewUuid);
if (!view) return next(new Error('Not found'));
if (view.type !== ViewTypes.FORM) return next(new Error('Not found'));
if (view.password && view.password !== req.body?.password) {
if (view.password && view.password !== req.headers?.['xc-password']) {
return res.status(403).json(ErrorMessages.INVALID_SHARED_VIEW_PASSWORD);
}
@ -169,12 +154,12 @@ async function dataInsert(
}
async function relDataList(req, res) {
const view = await View.getByUUID(req.params.publicDataUuid);
const view = await View.getByUUID(req.params.sharedViewUuid);
if (!view) NcError.notFound('Not found');
if (view.type !== ViewTypes.FORM) NcError.notFound('Not found');
if (view.password && view.password !== req.body?.password) {
if (view.password && view.password !== req.headers?.['xc-password']) {
NcError.forbidden(ErrorMessages.INVALID_SHARED_VIEW_PASSWORD);
}
@ -215,12 +200,12 @@ async function relDataList(req, res) {
}
export async function publicMmList(req: Request, res: Response) {
const view = await View.getByUUID(req.params.publicDataUuid);
const view = await View.getByUUID(req.params.sharedViewUuid);
if (!view) NcError.notFound('Not found');
if (view.type !== ViewTypes.GRID) NcError.notFound('Not found');
if (view.password && view.password !== req.body?.password) {
if (view.password && view.password !== req.headers?.['xc-password']) {
NcError.forbidden(ErrorMessages.INVALID_SHARED_VIEW_PASSWORD);
}
@ -271,12 +256,12 @@ export async function publicMmList(req: Request, res: Response) {
}
export async function publicHmList(req: Request, res: Response) {
const view = await View.getByUUID(req.params.publicDataUuid);
const view = await View.getByUUID(req.params.sharedViewUuid);
if (!view) NcError.notFound('Not found');
if (view.type !== ViewTypes.GRID) NcError.notFound('Not found');
if (view.password && view.password !== req.body?.password) {
if (view.password && view.password !== req.headers?.['xc-password']) {
NcError.forbidden(ErrorMessages.INVALID_SHARED_VIEW_PASSWORD);
}
@ -330,13 +315,16 @@ export async function publicHmList(req: Request, res: Response) {
}
const router = Router({ mergeParams: true });
router.post('/public/data/:publicDataUuid/list', catchError(dataList));
router.get(
'/api/v1/db/public/shared-view/:sharedViewUuid/rows',
catchError(dataList)
);
router.post(
'/public/data/:publicDataUuid/nested/:columnId',
'/api/v1/db/public/shared-view/:sharedViewUuid/nested/:columnId',
catchError(relDataList)
);
router.post(
'/public/data/:publicDataUuid/create',
'/api/v1/db/public/shared-view/:sharedViewUuid/create',
multer({
storage: multer.diskStorage({})
}).any(),
@ -344,11 +332,11 @@ router.post(
);
router.get(
'/public/data/:publicDataUuid/:rowId/mm/:colId',
'/api/v1/db/public/shared-view/:sharedViewUuid/:rowId/mm/:colId',
catchError(publicMmList)
);
router.get(
'/public/data/:publicDataUuid/:rowId/hm/:colId',
'/api/v1/db/public/shared-view/:sharedViewUuid/:rowId/hm/:colId',
catchError(publicHmList)
);

2
packages/nocodb/src/lib/noco/meta/api/publicApis/publicDataExportApis.ts

@ -17,7 +17,7 @@ async function exportCsv(req: Request, res: Response) {
if (!view) NcError.notFound('Not found');
if (view.type !== ViewTypes.GRID) NcError.notFound('Not found');
if (view.password && view.password !== req.body?.password) {
if (view.password && view.password !== req.headers?.['xc-password']) {
NcError.forbidden(ErrorMessages.INVALID_SHARED_VIEW_PASSWORD);
}

10
packages/nocodb/src/lib/noco/meta/api/publicApis/publicMetaApis.ts

@ -12,11 +12,11 @@ export async function viewMetaGet(req: Request, res: Response) {
const view: View & {
relatedMetas?: { [ket: string]: Model };
client?: string;
} = await View.getByUUID(req.params.sharedViewUuids);
} = await View.getByUUID(req.params.sharedViewUuid);
if (!view) NcError.notFound('Not found');
if (view.password && view.password !== req.body?.password) {
if (view.password && view.password !== req.headers?.['xc-password']) {
NcError.forbidden(ErrorMessages.INVALID_SHARED_VIEW_PASSWORD);
}
@ -78,13 +78,13 @@ async function publicSharedBaseGet(req, res): Promise<any> {
}
const router = Router({ mergeParams: true });
router.post(
'/api/v1/db/meta/public/shared-view/:sharedViewUuid/meta',
router.get(
'/api/v1/db/public/shared-view/:sharedViewUuid/meta',
catchError(viewMetaGet)
);
router.get(
'/api/v1/db/meta/public/shared-base/:sharedBaseUuid/meta',
'/api/v1/db/public/shared-base/:sharedBaseUuid/meta',
catchError(publicSharedBaseGet)
);
export default router;

72
scripts/sdk/swagger.json

@ -3395,6 +3395,14 @@
"name": "sharedViewUuid",
"in": "path",
"required": true
},
{
"schema": {
"type": "string"
},
"in": "header",
"name": "xc-password",
"description": "Shared view password"
}
],
"get": {
@ -3473,22 +3481,6 @@
"tags": [
"Public"
],
"requestBody": {
"content": {
"multipart/form-data": {
"schema": {
"type": "object",
"properties": {
"data": {},
"password": {
"type": "string"
}
}
}
}
},
"description": ""
},
"parameters": [
{
"schema": {
@ -3738,6 +3730,14 @@
"name": "columnName",
"in": "path",
"required": true
},
{
"schema": {
"type": "string"
},
"in": "header",
"name": "xc-password",
"description": "Shared view password"
}
],
"post": {
@ -3769,20 +3769,6 @@
"name": "offset"
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"password": {
"type": "string"
}
}
}
}
}
},
"tags": [
"Public"
],
@ -3798,9 +3784,17 @@
"name": "sharedViewUuid",
"in": "path",
"required": true
},
{
"schema": {
"type": "string"
},
"in": "header",
"name": "xc-password",
"description": "Shared view password"
}
],
"post": {
"get": {
"summary": "",
"operationId": "public-shared-view-meta-get",
"responses": {
@ -3823,21 +3817,7 @@
"Public"
],
"description": "",
"parameters": [],
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"password": {
"type": "string"
}
}
}
}
}
}
"parameters": []
}
},
"/api/v1/db/public/shared-base/{sharedBaseUuid}/meta": {

Loading…
Cancel
Save