mirror of https://github.com/nocodb/nocodb
346 changed files with 7899 additions and 4359 deletions
@ -1,6 +0,0 @@
|
||||
# COMPONENTS |
||||
|
||||
The components directory contains your Vue.js Components. |
||||
Nuxt.js doesn't supercharge these components. |
||||
|
||||
**This directory is not required, you can delete it if you don't want to use it.** |
@ -1,86 +0,0 @@
|
||||
const authorizedRoutes = {} |
||||
|
||||
authorizedRoutes['/user/settings'] = true |
||||
authorizedRoutes['/user/settings/accounts'] = true |
||||
authorizedRoutes['/user/settings/password'] = true |
||||
authorizedRoutes['/referral'] = true |
||||
|
||||
authorizedRoutes['/realestate/profits'] = true |
||||
authorizedRoutes['/realestate/bygeo'] = true |
||||
authorizedRoutes['/payment/buy'] = true |
||||
|
||||
authorizedRoutes['/pricing'] = false |
||||
authorizedRoutes['/user'] = true |
||||
|
||||
authorizedRoutes['/user/authentication'] = true |
||||
authorizedRoutes['/user/password'] = true |
||||
|
||||
authorizedRoutes['/error/400'] = false |
||||
authorizedRoutes['/realestate/capitalgains'] = true |
||||
authorizedRoutes['/payment/train'] = true |
||||
authorizedRoutes['/user/settings'] = true |
||||
|
||||
authorizedRoutes['/info/contact'] = false |
||||
authorizedRoutes['/profits'] = false |
||||
authorizedRoutes['/user/admin'] = true |
||||
authorizedRoutes['/error/403'] = false |
||||
authorizedRoutes['/error/404'] = false |
||||
|
||||
authorizedRoutes['/info/hiring'] = false |
||||
authorizedRoutes['/user/settings/accounts'] = true |
||||
authorizedRoutes['/user/password/reset'] = false |
||||
authorizedRoutes['/user/settings/profile'] = true |
||||
authorizedRoutes['/user/settings/picture'] = true |
||||
authorizedRoutes['/user/password/forgot'] = false |
||||
authorizedRoutes['/user/authentication/signup'] = false |
||||
authorizedRoutes['/user/settings/password'] = true |
||||
authorizedRoutes['/user/admin/user-edit'] = true |
||||
authorizedRoutes['/user/authentication/signin'] = false |
||||
authorizedRoutes['/user/password/reset/success'] = true |
||||
authorizedRoutes['/user/password/reset/invalid'] = true |
||||
authorizedRoutes['/user/password/reset/form'] = true |
||||
// // authorizedRoutes['/user/admin/user/_userId'] = true;
|
||||
// // authorizedRoutes['/'] = false;
|
||||
|
||||
// authorizedRoutes['/realestate/profits'] = true;
|
||||
|
||||
// let freeRoutes = {};
|
||||
// freeRoutes['/'] = true;
|
||||
// freeRoutes['/pricing'] = true;
|
||||
// freeRoutes['user/authentication/signin'] = true;
|
||||
// freeRoutes['user/authentication/signup'] = true;
|
||||
|
||||
exports.allowed = function(store, path) { |
||||
// console.log('store.getters.GtrUser',store.getters.GtrUser);
|
||||
// console.log('path',path);
|
||||
|
||||
// && authorizedRoutes[path]
|
||||
|
||||
if (store.getters.GtrUser === null && path in authorizedRoutes && authorizedRoutes[path]) { |
||||
return false |
||||
} else { |
||||
return true |
||||
} |
||||
} |
||||
/** |
||||
* @copyright Copyright (c) 2021, Xgene Cloud Ltd |
||||
* |
||||
* @author Naveen MR <oof1lab@gmail.com> |
||||
* @author Pranav C Balan <pranavxc@gmail.com> |
||||
* |
||||
* @license GNU AGPL version 3 or any later version |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License as |
||||
* published by the Free Software Foundation, either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* |
||||
*/ |
@ -0,0 +1,67 @@
|
||||
<template> |
||||
<div class="nc-container" :class="{active:modal}" @click="modal=false"> |
||||
<div class="nc-content elevation-3 pa-4" @click.stop> |
||||
<slot /> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
|
||||
export default { |
||||
name: 'NcSlider', |
||||
props: { |
||||
value: Boolean |
||||
}, |
||||
computed: { |
||||
modal: { |
||||
get() { |
||||
return this.value |
||||
}, |
||||
set(v) { |
||||
this.$emit('input', v) |
||||
} |
||||
} |
||||
}, |
||||
mounted() { |
||||
(document.querySelector('[data-app]') || this.$root.$el).append(this.$el) |
||||
}, |
||||
|
||||
destroyed() { |
||||
this.$el.parentNode && this.$el.parentNode.removeChild(this.$el) |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped lang="scss"> |
||||
|
||||
.nc-container { |
||||
position: fixed; |
||||
pointer-events: none; |
||||
width: 100vw; |
||||
height: 100vh; |
||||
z-index: 9999; |
||||
right: 0; |
||||
top: 0; |
||||
|
||||
.nc-content { |
||||
background-color: var(--v-backgroundColorDefault-base); |
||||
height: 100%; |
||||
width: max(50%, 700px); |
||||
position: absolute; |
||||
bottom: 0; |
||||
top: 0; |
||||
right: min(-50%, -700px); |
||||
transition: .3s right; |
||||
|
||||
} |
||||
|
||||
&.active { |
||||
pointer-events: all; |
||||
|
||||
& > .nc-content { |
||||
right: 0 |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,304 @@
|
||||
<template> |
||||
<v-dialog v-model="airtableModal" max-width="min(600px, 90%)"> |
||||
<v-card class="nc-import-card h-100"> |
||||
<v-toolbar class="elevation-0 align-center" height="68"> |
||||
<h3 class="mt-2"> |
||||
{{ $t('title.importFromAirtable') }} |
||||
</h3> |
||||
<div v-t="['c:airtable-import:turbo-mode']" class="ml-2 mt-3 title pointer" @click="enableTurbo"> |
||||
🚀 |
||||
</div> |
||||
<v-spacer /> |
||||
</v-toolbar> |
||||
|
||||
<v-divider /> |
||||
<div class="h-100" style="width: 100%"> |
||||
<div> |
||||
<v-card v-if="step === 1" class="py-6 elevation-0" height="500"> |
||||
<div class="d-flex flex-column justify-center align-center pt-2 pb-6"> |
||||
<span class="subtitle-1 font-weight-medium" @dblclick="$set(syncSource.details,'syncViews',true)"> |
||||
Credentials |
||||
</span> |
||||
|
||||
<a href="https://docs.nocodb.com" class="caption grey--text" target="_blank">Where to find this?</a> |
||||
</div> |
||||
|
||||
<v-form v-model="valid"> |
||||
<div v-if="syncSource" class="px-10 mt-1 mx-auto" style="max-width: 400px"> |
||||
<v-text-field |
||||
v-model="syncSource.details.apiKey" |
||||
outlined |
||||
dense |
||||
label="Api Key" |
||||
class="caption" |
||||
:type="isPasswordVisible ? 'text':'password'" |
||||
:rules="[v=> !!v || 'Api Key is required']" |
||||
> |
||||
<template #append=""> |
||||
<v-icon class="mt-1" small @click="isPasswordVisible = !isPasswordVisible"> |
||||
{{ isPasswordVisible ? 'visibility_off' : 'visibility' }} |
||||
</v-icon> |
||||
</template> |
||||
</v-text-field> |
||||
<v-text-field |
||||
v-model="syncSourceUrlOrId" |
||||
outlined |
||||
dense |
||||
label="Shared Base ID / URL" |
||||
class="caption" |
||||
:rules="[(v) => !!v || 'Shared Base ID / URL is required']" |
||||
/> |
||||
</div> |
||||
</v-form> <v-card-actions class="justify-center pb-6"> |
||||
<v-btn |
||||
v-t="['c:sync-airtable:save-and-sync']" |
||||
:disabled="!valid" |
||||
large |
||||
color="primary" |
||||
@click="saveAndSync" |
||||
> |
||||
Import |
||||
</v-btn> |
||||
</v-card-actions> |
||||
</v-card> |
||||
|
||||
<v-card |
||||
v-if="step === 2" |
||||
class="pb-4 mt-4 elevation-0" |
||||
> |
||||
<v-card-title class=" justify-center"> |
||||
<span class="subtitle-1 font-weight-medium">Logs</span> |
||||
</v-card-title> |
||||
|
||||
<v-card |
||||
ref="log" |
||||
dark |
||||
class="mt-2 mx-4 pa-4 elevation-0 green--text" |
||||
height="500" |
||||
style="overflow-y: auto" |
||||
> |
||||
<div v-for="({msg , status}, i) in progress" :key="i"> |
||||
<v-icon v-if="status==='FAILED'" color="red" size="15"> |
||||
mdi-close-circle-outline |
||||
</v-icon> |
||||
<v-icon v-else color="green" size="15"> |
||||
mdi-currency-usd |
||||
</v-icon> |
||||
<span class="caption nc-text">{{ msg }}</span> |
||||
</div> |
||||
<div |
||||
v-if="!progress || !progress.length || progress[progress.length-1].status !== 'COMPLETED' && progress[progress.length-1].status !== 'FAILED'" |
||||
class="" |
||||
> |
||||
<v-icon color="green" size="15"> |
||||
mdi-loading mdi-spin |
||||
</v-icon> |
||||
<span class="caption nc-text">Syncing |
||||
</span> |
||||
<!-- <div class="nc-progress" />--> |
||||
</div> |
||||
</v-card> |
||||
|
||||
<div |
||||
v-if="progress && progress.length && progress[progress.length-1].status === 'COMPLETED'" |
||||
class="pa-4 pt-8 text-center" |
||||
> |
||||
<v-btn large color="primary" @click="airtableModal=false"> |
||||
Go to dashboard |
||||
</v-btn> |
||||
</div> |
||||
</v-card> |
||||
</div> |
||||
</div> |
||||
</v-card> |
||||
</v-dialog> |
||||
</template> |
||||
|
||||
<script> |
||||
import io from 'socket.io-client' |
||||
|
||||
export default { |
||||
name: 'ImportFromAirtable', |
||||
props: { |
||||
value: Boolean |
||||
}, |
||||
data: () => ({ |
||||
isPasswordVisible: false, |
||||
valid: false, |
||||
socket: null, |
||||
step: 1, |
||||
progress: [], |
||||
syncSource: null, |
||||
syncSourceUrlOrId: '' |
||||
}), |
||||
computed: { |
||||
airtableModal: { |
||||
set(v) { |
||||
this.$emit('input', v) |
||||
}, |
||||
get() { |
||||
return this.value |
||||
} |
||||
} |
||||
}, |
||||
watch: { |
||||
syncSourceUrlOrId(v) { |
||||
if (this.syncSource && this.syncSource.details) { |
||||
const m = v && v.match(/(exp|shr).{14}/g) |
||||
this.syncSource.details.shareId = m ? m[0] : null |
||||
} |
||||
} |
||||
}, |
||||
created() { |
||||
this.socket = io(new URL(this.$axios.defaults.baseURL, window.location.href.split(/[?#]/)[0]).href, { |
||||
extraHeaders: { 'xc-auth': this.$store.state.users.token } |
||||
}) |
||||
this.socket.on('connect_error', () => { |
||||
this.socket.disconnect() |
||||
this.socket = null |
||||
}) |
||||
|
||||
const socket = this.socket |
||||
socket.on('connect', function(data) { |
||||
console.log(socket.id) |
||||
console.log('socket connected', data) |
||||
}) |
||||
|
||||
socket.on('progress', (d) => { |
||||
this.progress.push(d) |
||||
|
||||
this.$nextTick(() => { |
||||
if (this.$refs.log) { |
||||
const el = this.$refs.log.$el |
||||
el.scrollTop = el.scrollHeight |
||||
} |
||||
}) |
||||
|
||||
if (d.status === 'COMPLETED') { |
||||
this.$store.dispatch('project/_loadTables', { |
||||
dbKey: '0.projectJson.envs._noco.db.0', |
||||
key: '0.projectJson.envs._noco.db.0.tables', |
||||
_nodes: { |
||||
dbAlias: 'db', |
||||
env: '_noco', |
||||
type: 'tableDir' |
||||
} |
||||
}).then(() => this.$store.dispatch('tabs/loadFirstTableTab')) |
||||
} |
||||
}) |
||||
this.loadSyncSrc() |
||||
}, |
||||
beforeDestroy() { |
||||
if (this.socket) { |
||||
this.socket.disconnect() |
||||
} |
||||
}, |
||||
methods: { |
||||
async saveAndSync() { |
||||
await this.createOrUpdate() |
||||
this.sync() |
||||
}, |
||||
sync() { |
||||
this.step = 2 |
||||
this.$axios.post(`/api/v1/db/meta/syncs/${this.syncSource.id}/trigger`, this.payload, { |
||||
params: { |
||||
id: this.socket.id |
||||
} |
||||
}) |
||||
}, |
||||
async loadSyncSrc() { |
||||
const { data: { list: srcs } } = await this.$axios.get(`/api/v1/db/meta/projects/${this.projectId}/syncs`) |
||||
if (srcs && srcs[0]) { |
||||
srcs[0].details = srcs[0].details || {} |
||||
this.syncSource = srcs[0] |
||||
this.syncSourceUrlOrId = srcs[0].details.shareId |
||||
} else { |
||||
this.syncSource = { |
||||
type: 'Airtable', |
||||
details: { |
||||
syncInterval: '15mins', |
||||
syncDirection: 'Airtable to NocoDB', |
||||
syncRetryCount: 1, |
||||
|
||||
syncViews: false, |
||||
|
||||
apiKey: '', |
||||
shareId: '' |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
async createOrUpdate() { |
||||
try { |
||||
const { id, ...payload } = this.syncSource |
||||
if (id) { |
||||
await this.$axios.patch(`/api/v1/db/meta/syncs/${id}`, payload) |
||||
} else { |
||||
this.syncSource = (await this.$axios.post(`/api/v1/db/meta/projects/${this.projectId}/syncs`, payload)).data |
||||
} |
||||
} catch (e) { |
||||
this.$toast.error(await this._extractSdkResponseErrorMsg(e)).goAway(3000) |
||||
} |
||||
}, |
||||
enableTurbo() { |
||||
this.$set(this.syncSource.details, 'syncViews', true) |
||||
this.$toast.success('🚀🚀 Ludicrous mode activated! Let\'s go! 🚀🚀').goAway(3000) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
|
||||
.nc-progress { |
||||
margin-left: 12px; |
||||
position: relative; |
||||
width: 5px; |
||||
height: 5px; |
||||
border-radius: 5px; |
||||
background-color: #9880ff; |
||||
color: #9880ff; |
||||
animation: dotFlashing 1s infinite linear alternate; |
||||
animation-delay: .5s; |
||||
} |
||||
|
||||
.nc-progress::before, .nc-progress::after { |
||||
content: ''; |
||||
display: inline-block; |
||||
position: absolute; |
||||
top: 0; |
||||
} |
||||
|
||||
.nc-progress::before { |
||||
left: -7.5px; |
||||
width: 5px; |
||||
height: 5px; |
||||
border-radius: 5px; |
||||
background-color: #9880ff; |
||||
color: #9880ff; |
||||
animation: dotFlashing 1s infinite alternate; |
||||
animation-delay: 0s; |
||||
} |
||||
|
||||
.nc-progress::after { |
||||
left: 7.5px; |
||||
width: 5px; |
||||
height: 5px; |
||||
border-radius: 5px; |
||||
background-color: var(--v-primary-base); |
||||
color: var(--v-primary-base); |
||||
animation: dotFlashing 1s infinite alternate; |
||||
animation-delay: 1s; |
||||
} |
||||
|
||||
@keyframes dotFlashing { |
||||
0% { |
||||
background-color: var(--v-primary-base); |
||||
} |
||||
50%, |
||||
100% { |
||||
background-color: var(--v-backgroundColor-base); |
||||
} |
||||
} |
||||
|
||||
</style> |
@ -1,20 +1,22 @@
|
||||
import ExcelTemplateAdapter from '~/components/import/templateParsers/ExcelTemplateAdapter' |
||||
|
||||
export default class ExcelUrlTemplateAdapter extends ExcelTemplateAdapter { |
||||
constructor(url, $store, parserConfig) { |
||||
constructor(url, $store, parserConfig, $api) { |
||||
const name = url.split('/').pop() |
||||
super(name, null, parserConfig) |
||||
this.url = url |
||||
this.$api = $api |
||||
this.$store = $store |
||||
} |
||||
|
||||
async init() { |
||||
const res = await this.$store.dispatch('sqlMgr/ActSqlOp', [null, 'handleAxiosCall', |
||||
[{ |
||||
const data = await this.$api.utils.axiosRequestMake({ |
||||
apiMeta: { |
||||
url: this.url, |
||||
responseType: 'arraybuffer' |
||||
}]]) |
||||
this.excelData = res.data |
||||
} |
||||
}) |
||||
this.excelData = data.data |
||||
await super.init() |
||||
} |
||||
} |
||||
|
@ -1,404 +0,0 @@
|
||||
<template> |
||||
<div class="d-flex h-100"> |
||||
<v-navigation-drawer width="300" class="pa-1"> |
||||
<v-text-field |
||||
v-model="query" |
||||
outlined |
||||
dense |
||||
hide-details |
||||
placeholder="Search apps" |
||||
append-icon="mdi-magnify" |
||||
/> |
||||
|
||||
<v-list dense> |
||||
<v-list-item v-for="filter of filters" :key="filter"> |
||||
<v-checkbox |
||||
v-model="selectedTags" |
||||
class="pt-0 mt-0" |
||||
:value="filter" |
||||
hide-details |
||||
dense |
||||
:label="filter" |
||||
/> |
||||
</v-list-item> |
||||
</v-list> |
||||
</v-navigation-drawer> |
||||
<v-container class="h-100 app-container"> |
||||
<v-row> |
||||
<v-col v-for="(app,i) in filteredApps" :key="i" cols="6"> |
||||
<v-card |
||||
class="elevation-0 app-item-card" |
||||
> |
||||
<v-btn x-small outlined class="install-btn caption text-capitalize" @click="installApp"> |
||||
<v-icon x-small class="mr-1"> |
||||
mdi-plus |
||||
</v-icon> |
||||
Install |
||||
</v-btn> |
||||
|
||||
<div class="d-flex flex-no-wrap"> |
||||
<v-avatar |
||||
class="ma-3" |
||||
size="100" |
||||
tile |
||||
> |
||||
<v-img v-if="app.img" :src="app.img" contain /> |
||||
<v-img v-else src="https://cdn.vuetifyjs.com/images/cards/foster.jpg" contain /> |
||||
</v-avatar> |
||||
<div class="flex-grow-1"> |
||||
<v-card-title |
||||
class="title " |
||||
v-text="app.name" |
||||
/> |
||||
|
||||
<v-card-subtitle class="pb-1" v-text="app.description" /> |
||||
<v-card-actions> |
||||
<div class="d-flex justify-space-between d-100 align-center"> |
||||
<v-rating |
||||
full-icon="mdi-star" |
||||
readonly |
||||
length="5" |
||||
size="15" |
||||
value="5" |
||||
/> |
||||
|
||||
<span v-if="app.price && app.price !== 'Free'" class="subtitles">${{ app.price }} / mo</span> |
||||
<span v-else class="subtitles">Free</span> |
||||
</div> |
||||
</v-card-actions> |
||||
|
||||
<!-- <v-card-actions>--> |
||||
<!-- <v-btn--> |
||||
<!-- outlined--> |
||||
<!-- rounded--> |
||||
<!-- small--> |
||||
<!-- >--> |
||||
<!-- Download--> |
||||
<!-- </v-btn>--> |
||||
<!-- </v-card-actions>--> |
||||
</div> |
||||
</div> |
||||
</v-card> |
||||
</v-col> |
||||
</v-row> |
||||
</v-container> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
name: 'AppStore', |
||||
data: () => ({ |
||||
query: '', |
||||
selectedTags: [], |
||||
apps: [ |
||||
// { |
||||
// name: 'Graph', |
||||
// description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
// price: '29', |
||||
// tags: [] |
||||
// }, { |
||||
// name: 'Import / Export', |
||||
// description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
// price: '39' |
||||
// }, { |
||||
// name: 'Chart', |
||||
// description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
// price: '19' |
||||
// }, |
||||
{ |
||||
name: 'Freshworks', |
||||
img: require('~/assets/img/abcd/freshworks.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: '19', |
||||
tags: ['SaaS'] |
||||
}, |
||||
{ |
||||
name: 'RazorPay', |
||||
img: require('~/assets/img/abcd/razorpay.svg'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: '19', |
||||
tags: ['SaaS'] |
||||
}, |
||||
{ |
||||
name: 'Google Ads', |
||||
img: require('~/assets/img/abcd/adsense.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: '19', |
||||
tags: ['SaaS'] |
||||
}, |
||||
{ |
||||
name: 'Facebook Ads', |
||||
img: require('~/assets/img/abcd/fbads.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: '19', |
||||
tags: ['SaaS'] |
||||
}, |
||||
{ |
||||
name: 'Stripe', |
||||
img: require('~/assets/img/abcd/320.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: '19', |
||||
tags: ['SaaS'] |
||||
}, { |
||||
name: 'Twilio', |
||||
img: require('~/assets/img/abcd/twilio.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: '19', |
||||
tags: ['SaaS'] |
||||
}, { |
||||
name: 'SendGrid', |
||||
img: require('~/assets/img/abcd/sendgrid.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: '19', |
||||
tags: ['SaaS'] |
||||
}, { |
||||
name: 'Basecamp', |
||||
img: require('~/assets/img/abcd/basecamp.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: '19', |
||||
tags: ['SaaS'] |
||||
}, { |
||||
name: 'Github', |
||||
img: require('~/assets/img/abcd/github.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: '19', |
||||
tags: ['SaaS'] |
||||
}, { |
||||
name: 'Shopify', |
||||
img: require('~/assets/img/abcd/shopify.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: '19' |
||||
}, { |
||||
name: 'SAP', |
||||
img: require('~/assets/img/abcd/sap.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: '49', |
||||
tags: ['ERP'] |
||||
}, { |
||||
name: 'SalesForce', |
||||
img: require('~/assets/img/abcd/salesforce.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: '99', |
||||
tags: ['ERP'] |
||||
}, { |
||||
name: 'NetSuite', |
||||
img: require('~/assets/img/abcd/netsuit.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: '99' |
||||
}, { |
||||
name: 'Zoho CRM', |
||||
img: require('~/assets/img/abcd/zohocrm.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: '99', |
||||
tags: ['ERP'] |
||||
}, { |
||||
name: 'MySQL', |
||||
img: require('~/assets/img/abcd/mysql.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: 'Free', |
||||
tags: ['Free', 'Databases'] |
||||
}, { |
||||
name: 'PostgreSQL', |
||||
img: require('~/assets/img/abcd/pg.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: 'Free', |
||||
tags: ['Free', 'Databases'] |
||||
}, { |
||||
name: 'SQL Server', |
||||
img: require('~/assets/img/abcd/mssql.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: 'Free', |
||||
tags: ['Free', 'Databases'] |
||||
}, { |
||||
name: 'MariaDB', |
||||
img: require('~/assets/img/abcd/mariaDB.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: 'Free', |
||||
tags: ['Free', 'Databases'] |
||||
}, { |
||||
name: 'SQLite', |
||||
img: require('~/assets/img/temp/db/sqlite.svg'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: 'Free', |
||||
tags: ['Free', 'Databases'] |
||||
}, { |
||||
name: 'Oracle DB', |
||||
img: require('~/assets/img/temp/db/oracle.png.jpg'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: 'Free', |
||||
tags: ['Free', 'Databases'] |
||||
}, { |
||||
name: 'CrateDB', |
||||
img: require('~/assets/img/abcd/cratedb.jpg'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: '99', |
||||
tags: ['Databases'] |
||||
}, { |
||||
name: 'Cassandra', |
||||
img: require('~/assets/img/abcd/cassandra.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: '99', |
||||
tags: ['Databases'] |
||||
}, { |
||||
name: 'CouchDB', |
||||
img: require('~/assets/img/abcd/couchdb.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: '99', |
||||
tags: ['Databases'] |
||||
}, { |
||||
name: 'ElasticSearch', |
||||
img: require('~/assets/img/abcd/elasticsearch.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: '99', |
||||
tags: ['Databases'] |
||||
}, { |
||||
name: 'Snowflake', |
||||
img: require('~/assets/img/abcd/snowflake.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: '99', |
||||
tags: ['Databases'] |
||||
}, { |
||||
name: 'MongoDB', |
||||
img: require('~/assets/img/abcd/mongodb.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: '99' |
||||
}, { |
||||
name: 'BigQuery', |
||||
img: require('~/assets/img/abcd/bigquery.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: '99' |
||||
}, |
||||
|
||||
{ |
||||
name: 'REST API', |
||||
img: require('~/assets/img/abcd/rest.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: 'Free', |
||||
tags: ['Free', 'API'] |
||||
}, { |
||||
name: 'GRAPHQL API', |
||||
img: require('~/assets/img/abcd/graphql.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: 'Free', |
||||
tags: ['Free', 'API'] |
||||
}, { |
||||
name: 'gRPC API', |
||||
img: require('~/assets/img/abcd/grpc.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: 'Free', |
||||
tags: ['Free', 'API'] |
||||
}, |
||||
|
||||
{ |
||||
name: 'Swagger', |
||||
img: require('~/assets/img/abcd/swagger.png'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: 'Free', |
||||
tags: ['Free', 'API Specification'] |
||||
}, |
||||
{ |
||||
name: 'Postman', |
||||
img: require('~/assets/img/abcd/postman.jpg'), |
||||
description: 'Visualize your records on a bar, line, pie, or scatter chart', |
||||
price: 'Free', |
||||
tags: ['API Specification'] |
||||
} |
||||
|
||||
] |
||||
}), |
||||
computed: { |
||||
filters() { |
||||
return this.apps.reduce((arr, app) => arr.concat(app.tags || []), []).filter((f, i, arr) => i === arr.indexOf(f)).sort() |
||||
}, |
||||
filteredApps() { |
||||
return this.apps.filter(app => (!this.query.trim() || app.name.toLowerCase().includes(this.query.trim().toLowerCase())) && |
||||
(!this.selectedTags.length || this.selectedTags.some(t => app.tags && app.tags.includes(t))) |
||||
) |
||||
} |
||||
}, |
||||
methods: { |
||||
installApp() { |
||||
this.$toast.info('Coming soon after seed funding.').goAway(5000) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped lang="scss"> |
||||
.title { |
||||
color: var(--v-textColor-ligten2) !important; |
||||
} |
||||
|
||||
.app-item-card { |
||||
transition: .4s background-color; |
||||
position: relative; |
||||
overflow-x: hidden; |
||||
|
||||
.install-btn { |
||||
position: absolute; |
||||
opacity: 0; |
||||
right: -100%; |
||||
top: 10px; |
||||
transition: .4s opacity, .4s right; |
||||
} |
||||
|
||||
&:hover .install-btn { |
||||
right: 10px; |
||||
opacity: 1; |
||||
} |
||||
} |
||||
|
||||
.app-item-card { |
||||
transition: .4s background-color, .4s transform; |
||||
&:hover { |
||||
background: rgba(123, 126, 136, 0.1) !important; |
||||
transform: scale(1.01); |
||||
} |
||||
} |
||||
::v-deep { |
||||
.v-rating { |
||||
margin-left:6px; |
||||
.v-icon { |
||||
padding-right: 2px; |
||||
padding-left: 2px; |
||||
} |
||||
} |
||||
.v-input__control .v-input__slot .v-input--selection-controls__input { |
||||
transform: scale(.75); |
||||
} |
||||
|
||||
.v-input--selection-controls .v-input__slot > .v-label{ |
||||
font-size: .8rem; |
||||
} |
||||
} |
||||
.app-container { |
||||
height: 100%; |
||||
overflow-y: auto; |
||||
} |
||||
|
||||
</style> |
||||
<!-- |
||||
/** |
||||
* @copyright Copyright (c) 2021, Xgene Cloud Ltd |
||||
* |
||||
* @author Naveen MR <oof1lab@gmail.com> |
||||
* @author Pranav C Balan <pranavxc@gmail.com> |
||||
* |
||||
* @license GNU AGPL version 3 or any later version |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License as |
||||
* published by the Free Software Foundation, either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
--> |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue