mirror of https://github.com/nocodb/nocodb
Wing-Kam Wong
3 years ago
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' |
import ExcelTemplateAdapter from '~/components/import/templateParsers/ExcelTemplateAdapter' |
||||||
|
|
||||||
export default class ExcelUrlTemplateAdapter extends ExcelTemplateAdapter { |
export default class ExcelUrlTemplateAdapter extends ExcelTemplateAdapter { |
||||||
constructor(url, $store, parserConfig) { |
constructor(url, $store, parserConfig, $api) { |
||||||
const name = url.split('/').pop() |
const name = url.split('/').pop() |
||||||
super(name, null, parserConfig) |
super(name, null, parserConfig) |
||||||
this.url = url |
this.url = url |
||||||
|
this.$api = $api |
||||||
this.$store = $store |
this.$store = $store |
||||||
} |
} |
||||||
|
|
||||||
async init() { |
async init() { |
||||||
const res = await this.$store.dispatch('sqlMgr/ActSqlOp', [null, 'handleAxiosCall', |
const data = await this.$api.utils.axiosRequestMake({ |
||||||
[{ |
apiMeta: { |
||||||
url: this.url, |
url: this.url, |
||||||
responseType: 'arraybuffer' |
responseType: 'arraybuffer' |
||||||
}]]) |
} |
||||||
this.excelData = res.data |
}) |
||||||
|
this.excelData = data.data |
||||||
await super.init() |
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