Browse Source

feat: single shared view per view

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/679/head
Pranav C 3 years ago
parent
commit
d6251abdf6
  1. 10
      packages/nc-gui/components/project/spreadsheet/components/sharedViewsList.vue
  2. 3
      packages/nc-gui/components/project/spreadsheet/public/xcTable.vue
  3. 145
      packages/nocodb/src/lib/noco/meta/NcMetaMgr.ts
  4. 56
      packages/nocodb/src/lib/noco/meta/NcMetaMgrEE.ts

10
packages/nc-gui/components/project/spreadsheet/components/sharedViewsList.vue

@ -7,6 +7,9 @@
<th class="caption"> <th class="caption">
View Link View Link
</th> </th>
<th class="caption">
View name
</th>
<th class="caption"> <th class="caption">
Password Password
</th> </th>
@ -22,6 +25,9 @@
{{ `${dashboardUrl}#/nc/${link.view_type === 'form' ? 'form' : 'view'}/${link.view_id}` }} {{ `${dashboardUrl}#/nc/${link.view_type === 'form' ? 'form' : 'view'}/${link.view_id}` }}
</nuxt-link> </nuxt-link>
</td> </td>
<td class="caption">
{{ link.view_name }}
</td>
<td class="caption"> <td class="caption">
<template v-if="link.password"> <template v-if="link.password">
<span>{{ link.showPassword ? link.password : '***************************' }}</span> <span>{{ link.showPassword ? link.password : '***************************' }}</span>
@ -79,5 +85,7 @@ export default {
</script> </script>
<style scoped> <style scoped>
th,td{
padding: 0 5px;
}
</style> </style>

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

@ -396,6 +396,7 @@ export default {
} catch (e) { } catch (e) {
console.log(e) console.log(e)
} }
if (this.data.length) { if (this.data.length) {
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
const options = { const options = {
@ -567,6 +568,8 @@ export default {
this.notFound = true this.notFound = true
} else if (e.message === 'Invalid password') { } else if (e.message === 'Invalid password') {
this.showPasswordModal = true this.showPasswordModal = true
} else {
console.log(e)
} }
} }

145
packages/nocodb/src/lib/noco/meta/NcMetaMgr.ts

@ -3384,36 +3384,56 @@ export default class NcMetaMgr {
condition: { condition: {
model_name: args.args.model_name model_name: args.args.model_name
}, },
fields: ['id', 'view_id', 'password', 'model_name', 'view_type'] fields: [
'id',
'view_id',
'password',
'model_name',
'view_type',
'view_name'
]
} }
); );
} }
protected async getSharedViewData(req, args: any): Promise<any> { protected async getSharedViewData(req, args: any): Promise<any> {
try { try {
const viewMeta = await this.xcMeta const sharedViewMeta = await this.xcMeta
.knex('nc_shared_views') .knex('nc_shared_views')
.where({ .where({
view_id: args.args.view_id view_id: args.args.view_id
}) })
.first(); .first();
if (!sharedViewMeta) {
throw new Error('Meta not found');
}
const viewMeta = await this.xcMeta.metaGet(
sharedViewMeta.project_id,
sharedViewMeta.db_alias,
'nc_models',
{
title: sharedViewMeta.view_name
}
);
// if (viewMeta && viewMeta.password && viewMeta.password !== args.args.password) { // if (viewMeta && viewMeta.password && viewMeta.password !== args.args.password) {
// throw new Error('Invalid password') // throw new Error('Invalid password')
// } // }
if ( if (
viewMeta && sharedViewMeta &&
viewMeta.password && sharedViewMeta.password &&
viewMeta.password !== args.args.password sharedViewMeta.password !== args.args.password
) { ) {
throw new Error(this.INVALID_PASSWORD_ERROR); throw new Error(this.INVALID_PASSWORD_ERROR);
} }
const apiBuilder = this.app?.projectBuilders const apiBuilder = this.app?.projectBuilders
?.find(pb => pb.id === viewMeta.project_id) ?.find(pb => pb.id === sharedViewMeta.project_id)
?.apiBuilders?.find(ab => ab.dbAlias === viewMeta.db_alias); ?.apiBuilders?.find(ab => ab.dbAlias === sharedViewMeta.db_alias);
const model = apiBuilder?.xcModels?.[viewMeta.model_name]; const model = apiBuilder?.xcModels?.[sharedViewMeta.model_name];
if (model) { if (model) {
const queryParams = JSON.parse(viewMeta.query_params); const queryParams = JSON.parse(viewMeta.query_params);
@ -3430,8 +3450,8 @@ export default class NcMetaMgr {
const fields = queryParams?.fields || '*'; const fields = queryParams?.fields || '*';
return { return {
model_name: viewMeta.model_name, model_name: sharedViewMeta.model_name,
meta: apiBuilder?.getMeta(viewMeta.model_name), //JSON.parse(viewMeta.meta), meta: apiBuilder?.getMeta(sharedViewMeta.model_name), //JSON.parse(viewMeta.meta),
data: await model.list({ data: await model.list({
...req.query, ...req.query,
where, where,
@ -3452,21 +3472,34 @@ export default class NcMetaMgr {
protected async sharedViewNestedDataGet(_req, args: any): Promise<any> { protected async sharedViewNestedDataGet(_req, args: any): Promise<any> {
try { try {
const viewMeta = await this.xcMeta const sharedViewMeta = await this.xcMeta
.knex('nc_shared_views') .knex('nc_shared_views')
.where({ .where({
view_id: args.args.view_id view_id: args.args.view_id
}) })
.first(); .first();
if (!sharedViewMeta) {
throw new Error('Meta not found');
}
const viewMeta = await this.xcMeta.metaGet(
sharedViewMeta.project_id,
sharedViewMeta.db_alias,
'nc_models',
{
title: sharedViewMeta.view_name
}
);
if (!viewMeta) { if (!viewMeta) {
throw new Error('Not found'); throw new Error('Not found');
} }
if ( if (
viewMeta && sharedViewMeta &&
viewMeta.password && sharedViewMeta.password &&
viewMeta.password !== args.args.password sharedViewMeta.password !== args.args.password
) { ) {
throw new Error(this.INVALID_PASSWORD_ERROR); throw new Error(this.INVALID_PASSWORD_ERROR);
} }
@ -3477,8 +3510,8 @@ export default class NcMetaMgr {
// const queryParams = JSON.parse(viewMeta.query_params); // const queryParams = JSON.parse(viewMeta.query_params);
const apiBuilder = this.app?.projectBuilders const apiBuilder = this.app?.projectBuilders
?.find(pb => pb.id === viewMeta.project_id) ?.find(pb => pb.id === sharedViewMeta.project_id)
?.apiBuilders?.find(ab => ab.dbAlias === viewMeta.db_alias); ?.apiBuilders?.find(ab => ab.dbAlias === sharedViewMeta.db_alias);
// todo: only allow related table // todo: only allow related table
// if(tn &&){ // if(tn &&){
@ -3517,21 +3550,36 @@ export default class NcMetaMgr {
protected async sharedViewNestedChildDataGet(_req, args: any): Promise<any> { protected async sharedViewNestedChildDataGet(_req, args: any): Promise<any> {
try { try {
const viewMeta = await this.xcMeta // todo: replace with join query
const sharedViewMeta = await this.xcMeta
.knex('nc_shared_views') .knex('nc_shared_views')
.where({ .where({
view_id: args.args.view_id view_id: args.args.view_id
}) })
.first(); .first();
if (!sharedViewMeta) {
throw new Error('Meta not found');
}
const viewMeta = await this.xcMeta.metaGet(
sharedViewMeta.project_id,
sharedViewMeta.db_alias,
'nc_models',
{
title: sharedViewMeta.view_name
}
);
if (!viewMeta) { if (!viewMeta) {
throw new Error('Not found'); throw new Error('Not found');
} }
if ( if (
viewMeta && sharedViewMeta &&
viewMeta.password && sharedViewMeta.password &&
viewMeta.password !== args.args.password sharedViewMeta.password !== args.args.password
) { ) {
throw new Error(this.INVALID_PASSWORD_ERROR); throw new Error(this.INVALID_PASSWORD_ERROR);
} }
@ -3547,8 +3595,8 @@ export default class NcMetaMgr {
// const queryParams = JSON.parse(viewMeta.query_params); // const queryParams = JSON.parse(viewMeta.query_params);
const apiBuilder = this.app?.projectBuilders const apiBuilder = this.app?.projectBuilders
?.find(pb => pb.id === viewMeta.project_id) ?.find(pb => pb.id === sharedViewMeta.project_id)
?.apiBuilders?.find(ab => ab.dbAlias === viewMeta.db_alias); ?.apiBuilders?.find(ab => ab.dbAlias === sharedViewMeta.db_alias);
const model = apiBuilder.xcModels?.[tn]; const model = apiBuilder.xcModels?.[tn];
const parentMeta = apiBuilder.getMeta(ptn); const parentMeta = apiBuilder.getMeta(ptn);
@ -3617,21 +3665,33 @@ export default class NcMetaMgr {
} }
protected async sharedViewInsert(req, args: any): Promise<any> { protected async sharedViewInsert(req, args: any): Promise<any> {
const viewMeta = await this.xcMeta const sharedViewMeta = await this.xcMeta
.knex('nc_shared_views') .knex('nc_shared_views')
.where({ .where({
view_id: args.args.view_id view_id: args.args.view_id
}) })
.first(); .first();
if (!sharedViewMeta) {
throw new Error('Meta not found');
}
const viewMeta = await this.xcMeta.metaGet(
sharedViewMeta.project_id,
sharedViewMeta.db_alias,
'nc_models',
{
title: sharedViewMeta.view_name
}
);
if (!viewMeta) { if (!viewMeta) {
throw new Error('Not found'); throw new Error('Not found');
} }
if ( if (
viewMeta && sharedViewMeta &&
viewMeta.password && sharedViewMeta.password &&
viewMeta.password !== args.args.password sharedViewMeta.password !== args.args.password
) { ) {
throw new Error(this.INVALID_PASSWORD_ERROR); throw new Error(this.INVALID_PASSWORD_ERROR);
} }
@ -3642,8 +3702,8 @@ export default class NcMetaMgr {
const fields: string[] = queryParams?.fields.split(','); const fields: string[] = queryParams?.fields.split(',');
const apiBuilder = this.app?.projectBuilders const apiBuilder = this.app?.projectBuilders
?.find(pb => pb.id === viewMeta.project_id) ?.find(pb => pb.id === sharedViewMeta.project_id)
?.apiBuilders?.find(ab => ab.dbAlias === viewMeta.db_alias); ?.apiBuilders?.find(ab => ab.dbAlias === sharedViewMeta.db_alias);
const insertObject = Object.entries(args.args.data).reduce( const insertObject = Object.entries(args.args.data).reduce(
(obj, [key, val]) => { (obj, [key, val]) => {
@ -3661,7 +3721,7 @@ export default class NcMetaMgr {
} }
} }
const model = apiBuilder?.xcModels?.[viewMeta.model_name]; const model = apiBuilder?.xcModels?.[sharedViewMeta.model_name];
if (model) { if (model) {
req.query.form = viewMeta.view_name; req.query.form = viewMeta.view_name;
await model.nestedInsert(insertObject, null, req); await model.nestedInsert(insertObject, null, req);
@ -3669,21 +3729,34 @@ export default class NcMetaMgr {
} }
protected async sharedViewGet(_req, args: any): Promise<any> { protected async sharedViewGet(_req, args: any): Promise<any> {
const viewMeta = await this.xcMeta const sharedViewMeta = await this.xcMeta
.knex('nc_shared_views') .knex('nc_shared_views')
.where({ .where({
view_id: args.args.view_id view_id: args.args.view_id
}) })
.first(); .first();
if (!sharedViewMeta) {
throw new Error('Meta not found');
}
const viewMeta = await this.xcMeta.metaGet(
sharedViewMeta.project_id,
sharedViewMeta.db_alias,
'nc_models',
{
title: sharedViewMeta.view_name
}
);
if (!viewMeta) { if (!viewMeta) {
throw new Error('Not found'); throw new Error('Not found');
} }
if ( if (
viewMeta && sharedViewMeta &&
viewMeta.password && sharedViewMeta.password &&
viewMeta.password !== args.args.password sharedViewMeta.password !== args.args.password
) { ) {
throw new Error(this.INVALID_PASSWORD_ERROR); throw new Error(this.INVALID_PASSWORD_ERROR);
} }
@ -3691,11 +3764,11 @@ export default class NcMetaMgr {
// todo : filter out columns of related table // todo : filter out columns of related table
try { try {
const apiBuilder = this.app?.projectBuilders const apiBuilder = this.app?.projectBuilders
?.find(pb => pb.id === viewMeta.project_id) ?.find(pb => pb.id === sharedViewMeta.project_id)
?.apiBuilders?.find(ab => ab.dbAlias === viewMeta.db_alias); ?.apiBuilders?.find(ab => ab.dbAlias === sharedViewMeta.db_alias);
const tableMeta = (viewMeta.meta = apiBuilder?.getMeta( const tableMeta = (viewMeta.meta = apiBuilder?.getMeta(
viewMeta.model_name sharedViewMeta.model_name
)); ));
const relatedTableMetas = {}; const relatedTableMetas = {};

56
packages/nocodb/src/lib/noco/meta/NcMetaMgrEE.ts

@ -114,14 +114,26 @@ export default class NcMetaMgrEE extends NcMetaMgr {
protected async getSharedViewData(req, args: any): Promise<any> { protected async getSharedViewData(req, args: any): Promise<any> {
try { try {
console.log(args); const sharedViewMeta = await this.xcMeta
const viewMeta = await this.xcMeta
.knex('nc_shared_views') .knex('nc_shared_views')
.where({ .where({
view_id: args.args.view_id view_id: args.args.view_id
}) })
.first(); .first();
if (!sharedViewMeta) {
throw new Error('Meta not found');
}
const viewMeta = await this.xcMeta.metaGet(
sharedViewMeta.project_id,
sharedViewMeta.db_alias,
'nc_models',
{
title: sharedViewMeta.view_name
}
);
if ( if (
viewMeta && viewMeta &&
viewMeta.password && viewMeta.password &&
@ -131,11 +143,11 @@ export default class NcMetaMgrEE extends NcMetaMgr {
} }
const apiBuilder = this.app?.projectBuilders const apiBuilder = this.app?.projectBuilders
?.find(pb => pb.id === viewMeta.project_id) ?.find(pb => pb.id === sharedViewMeta.project_id)
?.apiBuilders?.find(ab => ab.dbAlias === viewMeta.db_alias); ?.apiBuilders?.find(ab => ab.dbAlias === sharedViewMeta.db_alias);
const model = apiBuilder?.xcModels?.[viewMeta.model_name]; const model = apiBuilder?.xcModels?.[sharedViewMeta.model_name];
let meta = apiBuilder?.getMeta(viewMeta.model_name); let meta = apiBuilder?.getMeta(sharedViewMeta.model_name);
if (!model) { if (!model) {
throw new Error('Meta not found'); throw new Error('Meta not found');
@ -211,7 +223,7 @@ export default class NcMetaMgrEE extends NcMetaMgr {
nestedParams.bt = nestedParams.bt.join(','); nestedParams.bt = nestedParams.bt.join(',');
return { return {
model_name: viewMeta.model_name, model_name: sharedViewMeta.model_name,
// meta, // meta,
// queryParams, // queryParams,
data: await model.nestedList({ data: await model.nestedList({
@ -244,13 +256,28 @@ export default class NcMetaMgrEE extends NcMetaMgr {
// ); // );
// } // }
// get existing shared view data if exist
let sharedView = await this.xcMeta.metaGet(
this.getProjectId(args),
this.getDbAlias(args),
'nc_shared_views',
{
model_name: args.args.model_name,
view_name: args.args.view_name,
view_type: args.args.show_as
},
['id', 'view_id', 'view_type']
);
if (!sharedView) {
const insertData = { const insertData = {
project_id: args.project_id, project_id: args.project_id,
db_alias: this.getDbAlias(args), db_alias: this.getDbAlias(args),
model_name: args.args.model_name, model_name: args.args.model_name,
view_name: args.args.view_name, view_name: args.args.view_name,
// meta: JSON.stringify(args.args.meta), // meta: JSON.stringify(args.args.meta),
query_params: JSON.stringify(args.args.query_params), // query_params: JSON.stringify(args.args.query_params),
view_id: uuidv4(), view_id: uuidv4(),
password: args.args.password, password: args.args.password,
view_type: args.args.show_as view_type: args.args.show_as
@ -262,22 +289,25 @@ export default class NcMetaMgrEE extends NcMetaMgr {
'nc_shared_views', 'nc_shared_views',
insertData insertData
); );
const res = await this.xcMeta.metaGet( sharedView = await this.xcMeta.metaGet(
this.getProjectId(args), this.getProjectId(args),
this.getDbAlias(args), this.getDbAlias(args),
'nc_shared_views', 'nc_shared_views',
insertData, insertData,
['id', 'view_id', 'view_type'] ['id', 'view_id', 'view_type']
); );
}
if (args.args.show_as === 'form') { if (args.args.show_as === 'form') {
res.url = `${req.ncSiteUrl}${this.config.dashboardPath}#/nc/form/${res.view_id}`; sharedView.url = `${req.ncSiteUrl}${this.config.dashboardPath}#/nc/form/${sharedView.view_id}`;
} else if (args.args.show_as === 'gallery') { } else if (args.args.show_as === 'gallery') {
res.url = `${req.ncSiteUrl}${this.config.dashboardPath}#/nc/gallery/${res.view_id}`; sharedView.url = `${req.ncSiteUrl}${this.config.dashboardPath}#/nc/gallery/${sharedView.view_id}`;
} else { } else {
res.url = `${req.ncSiteUrl}${this.config.dashboardPath}#/nc/view/${res.view_id}`; sharedView.url = `${req.ncSiteUrl}${this.config.dashboardPath}#/nc/view/${sharedView.view_id}`;
} }
Tele.emit('evt', { evt_type: 'sharedView:generated-link' }); Tele.emit('evt', { evt_type: 'sharedView:generated-link' });
return res; return sharedView;
} catch (e) { } catch (e) {
console.log(e); console.log(e);
} }

Loading…
Cancel
Save