Browse Source

feat: add sql views support(readonly)

re #135

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/865/head
Pranav C 3 years ago
parent
commit
5dee734e58
  1. 2
      packages/nc-gui/components/ProjectTreeView.vue
  2. 24
      packages/nc-gui/components/project/projectMetadata/disableOrEnableModels.vue
  3. 30
      packages/nc-gui/components/project/projectMetadata/sync/disableOrEnableRelations.vue
  4. 14
      packages/nc-gui/components/project/projectMetadata/sync/disableOrEnableTables.vue
  5. 17
      packages/nc-gui/components/project/projectMetadata/sync/disableOrEnableViews.vue
  6. 17
      packages/nc-gui/components/project/spreadsheet/components/cell.vue
  7. 40
      packages/nc-gui/components/project/view.vue
  8. 189
      packages/nc-gui/components/project/viewTabs/viewSpreadsheet.vue
  9. 6
      packages/nc-gui/helpers/rightClickOptions.js
  10. 2
      packages/nc-gui/helpers/treeViewDataSerializer.js
  11. 43
      packages/nc-gui/store/tabs.js
  12. 2
      packages/nocodb/src/lib/noco/NcProjectBuilderEE.ts
  13. 28
      packages/nocodb/src/lib/noco/gql/GqlApiBuilder.ts
  14. 29
      packages/nocodb/src/lib/noco/meta/NcMetaMgr.ts
  15. 28
      packages/nocodb/src/lib/noco/rest/RestApiBuilder.ts

2
packages/nc-gui/components/ProjectTreeView.vue

@ -184,7 +184,7 @@
<v-tooltip bottom>
<template #activator="{ on }">
<x-icon
v-if="_isUIAllowed('treeview-add-button')"
v-if="_isUIAllowed('treeview-add-button') && item.type !== 'viewDir'"
:color="['x-active', 'grey']"
small
v-on="on"

24
packages/nc-gui/components/project/projectMetadata/disableOrEnableModels.vue

@ -30,13 +30,17 @@
/>
</v-tab-item>
<!-- enable extra -->
<!-- <v-tab class="text-capitalize caption">Views</v-tab>
<v-tab-item>
<disable-or-enable-views
:nodes="nodes" :db="db"
:db-alias="db.meta.dbAlias"></disable-or-enable-views>
</v-tab-item>
<v-tab class="text-capitalize caption">Functions</v-tab>
<v-tab class="text-capitalize caption">
Views
</v-tab>
<v-tab-item>
<disable-or-enable-views
:nodes="nodes"
:db="db"
:db-alias="db.meta.dbAlias"
/>
</v-tab-item>
<!-- <v-tab class="text-capitalize caption">Functions</v-tab>
<v-tab-item>
<disable-or-enable-functions :nodes="nodes" :db="db"
:db-alias="db.meta.dbAlias"></disable-or-enable-functions>
@ -108,16 +112,18 @@
<script>
import { mapGetters } from 'vuex'
import XcMeta from '../settings/xcMeta'
import DisableOrEnableRelations from './sync/disableOrEnableRelations'
import { isMetaTable } from '@/helpers/xutils'
import DisableOrEnableTables from '@/components/project/projectMetadata/sync/disableOrEnableTables'
import ToggleTableUiAcl from '@/components/project/projectMetadata/uiAcl/toggleTableUIAcl'
import ToggleRelationsUiAcl from '@/components/project/projectMetadata/uiAcl/toggleRelationsUIAcl'
import XcMeta from '../settings/xcMeta'
import DisableOrEnableRelations from './sync/disableOrEnableRelations'
import DisableOrEnableViews from '~/components/project/projectMetadata/sync/disableOrEnableViews'
export default {
name: 'DisableOrEnableModels',
components: {
DisableOrEnableViews,
ToggleRelationsUiAcl,
ToggleTableUiAcl,
DisableOrEnableTables,

30
packages/nc-gui/components/project/projectMetadata/sync/disableOrEnableRelations.vue

@ -23,7 +23,7 @@
>
Reload
</x-btn>
<x-btn
<!-- <x-btn
outlined
tooltip="Toggle All"
small
@ -33,7 +33,7 @@
@click="toggleAll(toggle)"
>
Toggle All {{ toggle ? 'ON' : 'OFF' }}
</x-btn>
</x-btn>-->
<x-btn
outlined
tooltip="Save Changes"
@ -68,12 +68,22 @@
<template #header>
<thead>
<tr class="text-left caption">
<th>#</th>
<th>Table Name <span class="caption grey--text">({{ selectedCount }})</span></th>
<th>Relation</th>
<th>Parent</th>
<th>Child</th>
<th />
<th class="grey--text">
#
</th>
<th class="grey--text">
Table Name <span class="caption grey--text">({{ selectedCount }})</span>
</th>
<th class="grey--text">
Relation
</th>
<th class="grey--text">
Parent
</th>
<th class="grey--text">
Child
</th>
<!-- <th />-->
</tr>
</thead>
</template>
@ -85,7 +95,7 @@
<td>{{ item.relationType === 'hm' ? 'HasMany' : 'BelongsTo' }}</td>
<td>{{ item.rtn }}</td>
<td>{{ item.tn }}</td>
<td>
<!-- <td>
<v-checkbox
v-model="item.enabled"
class=""
@ -93,7 +103,7 @@
hide-details
@change="$set(item,'edited',true)"
/>
</td>
</td>-->
</tr>
</template>
</v-data-table>

14
packages/nc-gui/components/project/projectMetadata/sync/disableOrEnableTables.vue

@ -49,14 +49,16 @@
<v-simple-table dense style="min-width: 400px">
<thead>
<tr>
<th>
<th class="grey--text">
Models <span v-show="!isNewOrDeletedModelFound" class="caption ml-1">({{
enableCountText
}})</span>
</th>
<th>APIs</th>
<th>Actions</th>
<th>Comment</th>
<!-- <th>APIs</th>-->
<th class="grey--text">
Actions
</th>
<th />
</tr>
</thead>
<tbody>
@ -70,14 +72,14 @@
<span class="caption">{{ model.title }}</span>
</v-tooltip>
</td>
<td>
<!-- <td>
<v-checkbox
v-model="model.enabled"
dense
:disabled="model.new || model.deleted"
@change="edited = true"
/>
</td>
</td>-->
<td>
<template v-if="model.new">
<!-- <x-icon small color="success success" tooltip="Add and sync meta information"-->

17
packages/nc-gui/components/project/projectMetadata/sync/disableOrEnableViews.vue

@ -49,14 +49,17 @@
<v-simple-table dense style="min-width: 400px">
<thead>
<tr>
<th>
<th class="grey--text">
Models <span v-show="!isNewOrDeletedModelFound" class="caption ml-1">({{
enableCountText
}})</span>
</th>
<th>APIs</th>
<th>Actions</th>
<th>Comment</th>
<!-- <th>APIs</th>-->
<th class="grey--text">
Actions
</th>
<!-- <th>Comment</th>-->
<th />
</tr>
</thead>
<tbody>
@ -68,14 +71,14 @@
:key="model.title"
>
<td>{{ model.title }}</td>
<td>
<!-- <td>
<v-checkbox
v-model="model.enabled"
dense
:disabled="model.new || model.deleted"
@change="edited = true"
/>
</td>
</td>-->
<td>
<template v-if="model.new">
<!-- <x-icon small color="success success" tooltip="Add and sync meta information"-->
@ -263,7 +266,7 @@ export default {
this.views = (await this.$store.dispatch('sqlMgr/ActSqlOp', [{
dbAlias: this.db.meta.dbAlias,
env: this.$store.getters['project/GtrEnv']
}, 'viewList'])).data.list
}, 'viewList', { force: true }])).data.list
},
async saveModels() {

17
packages/nc-gui/components/project/spreadsheet/components/cell.vue

@ -15,31 +15,36 @@
<date-cell v-else-if="isDate" :value="value" />
<date-time-cell v-else-if="isDateTime" :value="value" />
<time-cell v-else-if="isTime" :value="value" />
<span v-else :class="{'long-text-cell' : isTextArea}">{{ value }}</span>
<span v-else :class="{'long-text-cell' : isTextArea}" :title="title">{{ value }}</span>
</template>
<script>
import DateCell from './cell/dateCell'
import DateTimeCell from './cell/dateTimeCell'
import TimeCell from './cell/timeCell'
import JsonCell from '@/components/project/spreadsheet/components/cell/jsonCell'
import UrlCell from '@/components/project/spreadsheet/components/cell/urlCell'
import cell from '@/components/project/spreadsheet/mixins/cell'
import SetListCell from '@/components/project/spreadsheet/components/cell/setListCell'
import EnumCell from '@/components/project/spreadsheet/components/cell/enumCell'
import EditableAttachmentCell from '@/components/project/spreadsheet/components/editableCell/editableAttachmentCell'
import DateCell from './cell/dateCell'
import DateTimeCell from './cell/dateTimeCell'
import TimeCell from './cell/timeCell'
export default {
name: 'TableCell',
components: { TimeCell, DateTimeCell, DateCell, JsonCell, UrlCell, EditableAttachmentCell, EnumCell, SetListCell },
mixins: [cell],
props: ['value', 'dbAlias', 'isLocked', 'selected'],
computed: {}
computed: {
title() {
if (typeof this.value === 'string') { return this.value }
return ''
}
}
}
</script>
<style scoped>
.long-text-cell{
.long-text-cell {
white-space: pre;
}
</style>

40
packages/nc-gui/components/project/view.vue

@ -1,8 +1,8 @@
<template>
<v-container class="pa-0 ma-0 h-100" fluid>
<v-tabs :key="!nodes.newView || created ? 'old' : 'new'" height="28" class="view-tab" color="pink">
<!-- <v-tab class="caption text-capitalize">
<!-- <v-tabs :key="!nodes.newView || created ? 'old' : 'new'" height="28" class="view-tab" color="pink">-->
<!-- <v-tab class="caption text-capitalize">
<v-icon small>mdi-table-column</v-icon>&nbsp;
Columns
@ -63,7 +63,7 @@
</template>
</template>-->
<!-- <v-tab class="caption text-capitalize">
<!-- <v-tab class="caption text-capitalize">
<v-icon small>mdi-shield-edit-outline</v-icon>&nbsp;
ACL
</v-tab>
@ -72,26 +72,26 @@
:nodes="nodes"
/>
</v-tab-item>-->
<template v-if="!nodes.newView || created">
<!-- <template v-if="!nodes.newView || created">
<v-tab class="caption text-capitalize">
<v-icon small>
mdi-table-row
</v-icon>&nbsp;
Spreadsheet
</v-tab>
<v-tab-item>
<!-- <rows-->
<!-- ref="tabs3"-->
<!-- :nodes="nodes"-->
<!-- />-->
<spreadsheet
class="h-100"
:nodes="nodes"
/>
</v-tab-item>
</template>
<template v-if="_isUIAllowed('view-create')">
<v-tab-item>-->
<!-- <rows-->
<!-- ref="tabs3"-->
<!-- :nodes="nodes"-->
<!-- />-->
<spreadsheet
class="h-100"
:nodes="nodes"
/>
<!-- </v-tab-item>
</template>-->
<!-- <template v-if="_isUIAllowed('view-create')">
<v-tab class="caption text-capitalize">
<v-icon small>
mdi-database-edit
@ -104,16 +104,16 @@
@created="created = true"
/>
</v-tab-item>
</template>
</v-tabs>
</template>-->
<!-- </v-tabs>-->
</v-container>
</template>
<script>
import { mapGetters } from 'vuex'
import Spreadsheet from '@/components/project/viewTabs/viewSpreadsheet'
import ViewQuery from './viewTabs/viewQuery'
import Spreadsheet from '@/components/project/viewTabs/viewSpreadsheet'
// import ViewColumns from './viewTabs/viewColumns'
export default {

189
packages/nc-gui/components/project/viewTabs/viewSpreadsheet.vue

@ -26,7 +26,7 @@
</v-icon>
</div>
</template>
<v-list dense>
<v-list v-if="meta" dense>
<v-list-item
v-for="col in meta.columns"
:key="col.cn"
@ -78,32 +78,49 @@
<column-filter-menu v-model="filters" :field-list="fieldList" />
<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--text' : cellHeight === h.size}" style="text-transform: capitalize">
{{ h.size }}
</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
<!-- <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>-->
<x-btn
tooltip="Toggle navigation drawer"
outlined
small
text
:btn-class="{ 'primary lighten-5 nc-toggle-nav-drawer' : !toggleDrawer}"
@click="toggleDrawer = !toggleDrawer"
>
<v-icon
small
class="mx-0"
color="grey darken-3"
>
{{ toggleDrawer ? 'mdi-door-closed' : 'mdi-door-open' }}
</v-icon>
</x-btn>
</v-toolbar>
<div
:class="`cell-height-${cellHeight}`"
@ -180,6 +197,7 @@
:nodes="nodes"
:table="table"
:meta="meta"
:toggle-drawer="toggleDrawer"
:primary-value-column="primaryValueColumn"
:concatenated-x-where="concatenatedXWhere"
:sort="sort"
@ -190,7 +208,7 @@
:sort-list.sync="sortList"
:show-fields.sync="showFields"
>
<v-list-item
<!-- <v-list-item
@click="showAdditionalFeatOverlay('view-columns')"
>
<v-icon x-small class="mr-2">
@ -205,7 +223,7 @@
mdi-shield-edit-outline
</v-icon>
<span class="caption"> ACL</span>
</v-list-item>
</v-list-item>-->
</spreadsheet-nav-drawer>
</div>
@ -219,22 +237,19 @@
<script>
import debounce from 'debounce'
import ApiFactory from '@/components/project/spreadsheet/apis/apiFactory'
// import Table from '@/components/project/table'
// import EditableCell from "@/components/project/spreadsheet/editableCell";
import { SqlUI } from '@/helpers/sqlUi/SqlUiFactory'
import FieldsMenu from '@/components/project/spreadsheet/components/fieldsMenu'
import SortListMenu from '@/components/project/spreadsheet/components/sortListMenu'
import ColumnFilterMenu from '@/components/project/spreadsheet/components/columnFilterMenu'
import XcGridView from '@/components/project/spreadsheet/views/xcGridView'
import SpreadsheetNavDrawer from '@/components/project/spreadsheet/components/spreadsheetNavDrawer'
import debounce from 'debounce'
import GalleryView from '@/components/project/spreadsheet/views/galleryView'
import KanbanView from '@/components/project/spreadsheet/views/kanbanView'
import CalendarView from '@/components/project/spreadsheet/views/calendarView'
import AdditionalFeatures from '@/components/project/spreadsheet/overlay/additinalFeatures'
import spreadsheet from '@/components/project/spreadsheet/mixins/spreadsheet'
// import ExpandedForm from "@/components/project/spreadsheet/expandedForm";
export default {
name: 'Spreadsheet',
@ -261,6 +276,10 @@ export default {
relationPrimaryValue: [String, Number]
},
data: () => ({
syncDataDebounce: debounce(async function(self) {
await self.syncData()
}, 500),
fieldsOrder: [],
showAddFeatOverlay: false,
featureType: null,
selectedViewId: null,
@ -276,7 +295,7 @@ export default {
showExpandModal: false,
selectedExpandRowIndex: null,
selectedExpandRowMeta: null,
meta: [],
meta: null,
navDrawer: true,
selected: {
row: null,
@ -303,7 +322,7 @@ export default {
},
filteredData: [],
showFields: {},
fieldList: [],
// fieldList: [],
cellHeights: [{
size: 'small',
@ -321,6 +340,21 @@ export default {
rowContextMenu: null,
modelName: null
}),
computed: {
sqlUi() {
// todo: replace with correct client
return SqlUI.create(this.nodes.dbConnection)
},
api() {
return ApiFactory.create(this.$store.getters['project/GtrProjectType'], (this.meta && this.meta._tn) || this.table, this.meta && this.meta.columns, this, this.meta)
},
edited() {
return this.data && this.data.some(r => r.rowMeta && (r.rowMeta.new || r.rowMeta.changed))
},
table() {
return this.nodes.tn || this.nodes.view_name
}
},
async mounted() {
try {
await this.loadMeta()
@ -348,25 +382,62 @@ export default {
}
this.searchField = this.primaryValueColumn
},
created() {
if (this.relationType === 'hm') {
this.filters.push({
field: this.relation.cn,
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() {
document.removeEventListener('keydown', this.onKeyDown)
},
methods: {
syncDataDebounce: debounce(async function(self) {
await self.syncData()
}, 500),
// syncDataDebounce: debounce(async function(self) {
// await self.syncData()
// }, 500),
async syncData() {
if (this.relation) {
return
}
try {
const queryParams = {
filters: this.filters,
sortList: this.sortList,
showFields: this.showFields
showFields: this.showFields,
fieldsOrder: this.fieldsOrder,
viewStatus: this.viewStatus,
columnsWidth: this.columnsWidth,
showSystemFields: this.showSystemFields,
extraViewParams: this.extraViewParams
}
if (this.isGallery) {
queryParams.coverImageField = this.coverImageField
}
this.$set(this.selectedView, 'query_params', JSON.stringify(queryParams))
if (!this._isUIAllowed('xcVirtualTableUpdate')) { return }
if (!this._isUIAllowed('xcVirtualTableUpdate')) {
return
}
await this.sqlOp({ dbAlias: this.nodes.dbAlias }, 'xcVirtualTableUpdate', {
id: this.selectedViewId,
query_params: queryParams
query_params: queryParams,
tn: this.meta.tn,
view_name: this.$route.query.view
})
} catch (e) {
// this.$toast.error(e.message).goAway(3000);
@ -479,42 +550,6 @@ export default {
}))
this.loadingData = false
}
},
computed: {
sqlUi() {
// todo: replace with correct client
return SqlUI.create(this.nodes.dbConnection)
},
api() {
return ApiFactory.create(this.$store.getters['project/GtrProjectType'], (this.meta && this.meta._tn) || this.table, this.meta && this.meta.columns, this, this.meta)
},
edited() {
return this.data && this.data.some(r => r.rowMeta && (r.rowMeta.new || r.rowMeta.changed))
},
table() {
return this.nodes.tn || this.nodes.view_name
}
},
created() {
if (this.relationType === 'hm') {
this.filters.push({
field: this.relation.cn,
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() {
document.removeEventListener('keydown', this.onKeyDown)
}
}
</script>

6
packages/nc-gui/helpers/rightClickOptions.js

@ -25,7 +25,7 @@ export default {
...(process.env.NODE_ENV === 'dev' ? { 'Show _Nodes Info': 'SHOW_NODES' } : {})
},
viewDir: {
'View Create': 'ENV_DB_VIEWS_CREATE',
// 'View Create': 'ENV_DB_VIEWS_CREATE',
'Views Refresh': 'ENV_DB_VIEWS_REFRESH',
...(process.env.NODE_ENV === 'dev' ? { 'Show _Nodes Info': 'SHOW_NODES' } : {})
},
@ -75,8 +75,8 @@ export default {
...(process.env.NODE_ENV === 'dev' ? { 'Show _Nodes Info': 'SHOW_NODES' } : {})
},
view: {
'View Rename': 'ENV_DB_VIEWS_RENAME',
'View Delete': 'ENV_DB_VIEWS_DELETE',
// 'View Rename': 'ENV_DB_VIEWS_RENAME',
// 'View Delete': 'ENV_DB_VIEWS_DELETE',
...(process.env.NODE_ENV === 'dev' ? { 'Show _Nodes Info': 'SHOW_NODES' } : {})
},
function: {

2
packages/nc-gui/helpers/treeViewDataSerializer.js

@ -87,7 +87,7 @@ function dbparser(data, envKey, env) {
json.children.push(tableParser(db.tables, dbKey, env, db.meta.dbAlias, db));
// enable extra
// json.children.push(viewsParser(db.views, dbKey, env, db.meta.dbAlias, db));
json.children.push(viewsParser(db.views, dbKey, env, db.meta.dbAlias, db));
// if (db.client !== 'sqlite3')
// json.children.push(functionsParser(db.functions, dbKey, env, db.meta.dbAlias, db));

43
packages/nc-gui/store/tabs.js

@ -107,9 +107,33 @@ export const actions = {
} = this.$router.currentRoute.query
try {
let tabNode
await dispatch('project/_loadTables', {
dbKey: '0.projectJson.envs._noco.db.0',
key: '0.projectJson.envs._noco.db.0.tables',
_nodes: {
dbAlias: 'db',
// dbKey: "0.projectJson.envs._noco.db.0",
env: '_noco',
// key: "0.projectJson.envs._noco.db.0.tables",
type: 'tableDir'
}
}, { root: true })
await dispatch('project/_loadViews', {
dbKey: '0.projectJson.envs._noco.db.0',
key: '0.projectJson.envs._noco.db.0.views',
_nodes: {
dbAlias: 'db',
// dbKey: "0.projectJson.envs._noco.db.0",
env: '_noco',
// key: "0.projectJson.envs._noco.db.0.tables",
type: 'viewDir'
}
}, { root: true })
switch (type) {
case 'table':
await dispatch('project/_loadTables', {
/* await dispatch('project/_loadTables', {
dbKey: '0.projectJson.envs._noco.db.0',
key: '0.projectJson.envs._noco.db.0.tables',
_nodes: {
@ -119,7 +143,7 @@ export const actions = {
// key: "0.projectJson.envs._noco.db.0.tables",
type: 'tableDir'
}
}, { root: true })
}, { root: true }) */
tabNode = rootState.project
.list[0] // project
.children[0] // environment
@ -129,7 +153,7 @@ export const actions = {
break
case 'view':
await dispatch('project/_loadViews', {
/* await dispatch('project/_loadViews', {
dbKey: '0.projectJson.envs._noco.db.0',
key: '0.projectJson.envs._noco.db.0.views',
_nodes: {
@ -139,7 +163,7 @@ export const actions = {
// key: "0.projectJson.envs._noco.db.0.tables",
type: 'viewDir'
}
}, { root: true })
}, { root: true }) */
tabNode = rootState.project
.list[0] // project
.children[0] // environment
@ -255,17 +279,6 @@ export const actions = {
}
})
} else {
await dispatch('project/_loadTables', {
dbKey: '0.projectJson.envs._noco.db.0',
key: '0.projectJson.envs._noco.db.0.tables',
_nodes: {
dbAlias: 'db',
// dbKey: "0.projectJson.envs._noco.db.0",
env: '_noco',
// key: "0.projectJson.envs._noco.db.0.tables",
type: 'tableDir'
}
}, { root: true })
const nodes = rootState.project
.list[0] // project
.children[0] // environment

2
packages/nocodb/src/lib/noco/NcProjectBuilderEE.ts

@ -43,7 +43,7 @@ export default class NcProjectBuilderEE extends NcProjectBuilder {
case 'viewMetaCreate':
// await curBuilder.onTableCreate(data.req.args.tn)
await curBuilder.xcTablesPopulate({
tableNames: data.req.args.viewNames,
tableNames: data.req.args.viewNames.map(tn => ({ tn })),
type: 'view'
});
break;

28
packages/nocodb/src/lib/noco/gql/GqlApiBuilder.ts

@ -770,18 +770,22 @@ export class GqlApiBuilder extends BaseApiBuilder<Noco> implements XcMetaMgr {
);
// enable extra
// tables.push(...(await this.sqlClient.viewList())?.data?.list?.map(v => {
// this.viewsCount++;
// v.type = 'view';
// v.tn = v.view_name;
// return v;
// }).filter(v => {
// /* filter based on prefix */
// if (this.projectBuilder?.prefix) {
// return v.view_name.startsWith(this.projectBuilder?.prefix)
// }
// return true;
// }));
tables.push(
...(await this.sqlClient.viewList())?.data?.list
?.map(v => {
this.viewsCount++;
v.type = 'view';
v.tn = v.view_name;
return v;
})
.filter(v => {
/* filter based on prefix */
if (this.projectBuilder?.prefix) {
return v.view_name.startsWith(this.projectBuilder?.prefix);
}
return true;
})
);
// enable extra
// let functions = [];
// let procedures = [];

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

@ -4044,6 +4044,7 @@ export default class NcMetaMgr {
...viewMeta.meta,
columns: viewMeta.meta.columns.filter(
c =>
!viewMeta.query_params?.showFields ||
viewMeta.query_params?.showFields?.[c._cn] ||
c.pk ||
viewMeta.meta.v?.some(v => v.bt?.cn === c.cn)
@ -4216,7 +4217,10 @@ export default class NcMetaMgr {
const roles = req.session?.passport?.user?.roles;
const views = (
await this.xcVisibilityMetaGet({ ...args, args: { type: 'view' } })
await this.xcVisibilityMetaGet({
...args,
args: { type: 'view', ...args.args }
})
).filter((view: any) => {
return Object.keys(roles).some(
role => roles[role] && !view.disabled[role]
@ -4597,7 +4601,8 @@ export default class NcMetaMgr {
case 'view':
{
// const views = (await sqlClient.viewList())?.data?.list;
const views = await this.xcMeta.metaList(
let views = await this.xcMeta.metaList(
this.getProjectId(args),
this.getDbAlias(args),
'nc_models',
@ -4608,8 +4613,26 @@ export default class NcMetaMgr {
}
);
if (args.args.force) {
views = (await sqlClient.viewList())?.data?.list?.map(view => {
return (
views.find(mod => mod.title === view.view_name) ?? {
title: view.view_name,
alias: view.view_name
}
);
});
const config = this.projectConfigs[this.getProjectId(args)];
views = config?.prefix
? views.filter(t => {
t.alias = t.title.replace(config?.prefix, '');
return t.title.startsWith(config?.prefix);
})
: views;
}
const result = views.reduce((obj, view) => {
obj[view.view_name] = {
obj[view.view_name || view.title] = {
view_name: view.title,
_tn: view.alias,
disabled: { ...defaultDisabled }

28
packages/nocodb/src/lib/noco/rest/RestApiBuilder.ts

@ -401,18 +401,22 @@ export class RestApiBuilder extends BaseApiBuilder<Noco> {
);
// enable extra
/* tables.push(...(await this.sqlClient.viewList())?.data?.list?.map(v => {
this.viewsCount++;
v.type = 'view';
v.tn = v.view_name;
return v;
}).filter(v => {
/!* filter based on prefix *!/
if (this.projectBuilder?.prefix) {
return v.view_name.startsWith(this.projectBuilder?.prefix)
}
return true;
}));*/
tables.push(
...(await this.sqlClient.viewList())?.data?.list
?.map(v => {
this.viewsCount++;
v.type = 'view';
v.tn = v.view_name;
return v;
})
.filter(v => {
/* filter based on prefix */
if (this.projectBuilder?.prefix) {
return v.view_name.startsWith(this.projectBuilder?.prefix);
}
return true;
})
);
// enable extra
await this.populteProcedureAndFunctionRoutes();

Loading…
Cancel
Save