mirror of https://github.com/nocodb/nocodb
29 changed files with 16992 additions and 0 deletions
@ -0,0 +1,8 @@ |
|||||||
|
node_modules |
||||||
|
*.log* |
||||||
|
.nuxt |
||||||
|
.nitro |
||||||
|
.cache |
||||||
|
.output |
||||||
|
.env |
||||||
|
dist |
@ -0,0 +1,42 @@ |
|||||||
|
# Nuxt 3 Minimal Starter |
||||||
|
|
||||||
|
Look at the [nuxt 3 documentation](https://v3.nuxtjs.org) to learn more. |
||||||
|
|
||||||
|
## Setup |
||||||
|
|
||||||
|
Make sure to install the dependencies: |
||||||
|
|
||||||
|
```bash |
||||||
|
# yarn |
||||||
|
yarn install |
||||||
|
|
||||||
|
# npm |
||||||
|
npm install |
||||||
|
|
||||||
|
# pnpm |
||||||
|
pnpm install --shamefully-hoist |
||||||
|
``` |
||||||
|
|
||||||
|
## Development Server |
||||||
|
|
||||||
|
Start the development server on http://localhost:3000 |
||||||
|
|
||||||
|
```bash |
||||||
|
npm run dev |
||||||
|
``` |
||||||
|
|
||||||
|
## Production |
||||||
|
|
||||||
|
Build the application for production: |
||||||
|
|
||||||
|
```bash |
||||||
|
npm run build |
||||||
|
``` |
||||||
|
|
||||||
|
Locally preview production build: |
||||||
|
|
||||||
|
```bash |
||||||
|
npm run preview |
||||||
|
``` |
||||||
|
|
||||||
|
Checkout the [deployment documentation](https://v3.nuxtjs.org/guide/deploy/presets) for more information. |
@ -0,0 +1,6 @@ |
|||||||
|
<template> |
||||||
|
<!-- <NuxtLayout>--> |
||||||
|
<!-- <NuxtPage />--> |
||||||
|
<!-- </NuxtLayout>--> |
||||||
|
<NuxtPage/> |
||||||
|
</template> |
After Width: | Height: | Size: 67 KiB |
@ -0,0 +1,30 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<TabMenu :model="tabItems" v-model:activeIndex="activeTab"/> |
||||||
|
<template v-if="tabItems && tabItems[activeTab]"> |
||||||
|
<TabsSmartsheet :tab-meta="tabs[activeTab]" :key="tabs[activeTab].id"/> |
||||||
|
</template> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup lang="ts"> |
||||||
|
|
||||||
|
import {useTabs} from "~/composables/tabs"; |
||||||
|
|
||||||
|
const {tabs,activeTab} = useTabs() |
||||||
|
|
||||||
|
const tabItems = computed(() => { |
||||||
|
return tabs.value.map(tab => { |
||||||
|
return { |
||||||
|
label: tab.title, |
||||||
|
// icon: tab.icon, |
||||||
|
closable: true |
||||||
|
} |
||||||
|
}) |
||||||
|
}) |
||||||
|
|
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped> |
||||||
|
|
||||||
|
</style> |
@ -0,0 +1,24 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
|
||||||
|
<div v-for="table in tables" class="p-2 text-sm pointer" |
||||||
|
@click="addTab({type:'table',title:table.title, id:table.id})"> |
||||||
|
{{ table.title }} |
||||||
|
</div> |
||||||
|
|
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup lang="ts"> |
||||||
|
import {useProject} from "~/composables/project"; |
||||||
|
import {useTabs} from "~/composables/tabs"; |
||||||
|
|
||||||
|
const {tables} = useProject() |
||||||
|
const {addTab} = useTabs() |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped> |
||||||
|
.pointer{ |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,56 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
|
||||||
|
<div class="card"> |
||||||
|
<DataTable :value="rows" responsiveLayout="scroll"> |
||||||
|
|
||||||
|
<Column v-for="col in meta.columns" :key="col.id" :field="col.title" :header="col.title"> |
||||||
|
<template v-if="col.uidt === 'LinkToAnotherRecord'" #body="{data:{[col.title]:d}}"> |
||||||
|
{{ d&& (Array.isArray(d) ? d : [d]).map(c1 => c1[Object.keys(c1)[1]]).join(', ') }} |
||||||
|
</template> |
||||||
|
</Column> |
||||||
|
</DataTable> |
||||||
|
</div> |
||||||
|
|
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script lang="ts" setup> |
||||||
|
import {useNuxtApp} from "#app"; |
||||||
|
import {Api} from "nocodb-sdk"; |
||||||
|
import {useUser} from "~/composables/user"; |
||||||
|
|
||||||
|
const {tabMeta, meta} = defineProps({ |
||||||
|
tabMeta: Object, |
||||||
|
meta: Object |
||||||
|
}) |
||||||
|
|
||||||
|
const {project} = useProject() |
||||||
|
const {user} = useUser() |
||||||
|
const rows = ref() |
||||||
|
|
||||||
|
const {$api}: { $api: Api<any> } = useNuxtApp() as any |
||||||
|
|
||||||
|
|
||||||
|
const loadData = async () => { |
||||||
|
const response = await $api.dbTableRow.list('noco', |
||||||
|
project.value.id, |
||||||
|
meta.id, {}, { |
||||||
|
headers: { |
||||||
|
'xc-auth': user.token |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
rows.value = response.list |
||||||
|
} |
||||||
|
|
||||||
|
onMounted(async () => { |
||||||
|
await loadData() |
||||||
|
}) |
||||||
|
|
||||||
|
|
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped> |
||||||
|
|
||||||
|
</style> |
@ -0,0 +1,36 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<template v-if="meta && tabMeta"> |
||||||
|
<SmartsheetGrid :meta="meta" :tabMeta="tabMeta"></SmartsheetGrid> |
||||||
|
</template> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup lang="ts"> |
||||||
|
import {useMetas} from "~/composables/metas"; |
||||||
|
import {computed, onMounted, watch} from 'vue' |
||||||
|
|
||||||
|
const {tabMeta} = defineProps({ |
||||||
|
tabMeta: Object |
||||||
|
}) |
||||||
|
|
||||||
|
const {getMeta, metas} = useMetas() |
||||||
|
|
||||||
|
const meta = computed(() => { |
||||||
|
return metas.value?.[tabMeta?.id] |
||||||
|
}) |
||||||
|
|
||||||
|
onMounted(async () => { |
||||||
|
await getMeta(tabMeta?.id) |
||||||
|
}) |
||||||
|
|
||||||
|
watch(() => tabMeta && tabMeta?.id, async (newVal, oldVal) => { |
||||||
|
if (newVal !== oldVal) { |
||||||
|
await getMeta(newVal) |
||||||
|
} |
||||||
|
}) |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped> |
||||||
|
|
||||||
|
</style> |
@ -0,0 +1,41 @@ |
|||||||
|
import {useNuxtApp, useState} from "#app"; |
||||||
|
import {Api, TableType} from "nocodb-sdk"; |
||||||
|
import {useUser} from "~/composables/user"; |
||||||
|
import {useProject} from "~/composables/project"; |
||||||
|
|
||||||
|
|
||||||
|
export const useMetas = () => { |
||||||
|
const {$api}: { $api: Api<any> } = useNuxtApp() as any |
||||||
|
const {user} = useUser() |
||||||
|
const {tables} = useProject() |
||||||
|
|
||||||
|
const metas = useState<{ [idOrTitle: string]: TableType | any }>('metas', () => ({})) |
||||||
|
|
||||||
|
const getMeta = async (tableIdOrTitle: string, force = false) => { |
||||||
|
if (!force && metas[tableIdOrTitle]) { |
||||||
|
return metas[tableIdOrTitle] |
||||||
|
} |
||||||
|
|
||||||
|
const modelId = (tables.value.find(t => t.title === tableIdOrTitle || t.id === tableIdOrTitle) || {}).id |
||||||
|
if (!modelId) { |
||||||
|
console.warn(`Table '${tableIdOrTitle}' is not found in the table list`) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
const model = await $api.dbTable.read(modelId, { |
||||||
|
headers: { |
||||||
|
'xc-auth': user.token |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
metas.value = { |
||||||
|
...metas.value, |
||||||
|
[model.id]: model, |
||||||
|
[model.title]: model |
||||||
|
} |
||||||
|
|
||||||
|
return model |
||||||
|
} |
||||||
|
|
||||||
|
return {getMeta, metas} |
||||||
|
} |
@ -0,0 +1,36 @@ |
|||||||
|
import {useNuxtApp} from "#app"; |
||||||
|
import {Api, TableType} from "nocodb-sdk"; |
||||||
|
import {useUser} from "~/composables/user"; |
||||||
|
|
||||||
|
export const useProject = () => { |
||||||
|
const {$api}: { $api: Api<any> } = useNuxtApp() as any |
||||||
|
const {user} = useUser() |
||||||
|
|
||||||
|
const project = useState<{ id?: string, title?: string }>('project', null) |
||||||
|
const tables = useState<Array<TableType>>('tables', null) |
||||||
|
|
||||||
|
const loadTables = async () => { |
||||||
|
const tablesResponse = await $api.dbTable.list(project?.value?.id, {}, { |
||||||
|
headers: { |
||||||
|
'xc-auth': user.token |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
console.log(tablesResponse) |
||||||
|
tables.value = tablesResponse.list |
||||||
|
} |
||||||
|
|
||||||
|
const loadProject = async (projectId:string) => { |
||||||
|
const projectResponse = await $api.project.read(projectId, { |
||||||
|
headers: { |
||||||
|
'xc-auth': user.token |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
console.log(projectResponse) |
||||||
|
project.value = projectResponse |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
return {project, tables, loadProject, loadTables} |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
import {useState} from "#app"; |
||||||
|
|
||||||
|
interface TabItem { |
||||||
|
type: 'table' | 'view', |
||||||
|
title: string, |
||||||
|
id:string |
||||||
|
} |
||||||
|
|
||||||
|
export const useTabs = () => { |
||||||
|
const tabs = useState<Array<TabItem>>('tabs', () => []) |
||||||
|
const activeTab = useState<number>('activeTab', ()=>0) |
||||||
|
|
||||||
|
const addTab = (tabMeta: TabItem) => { |
||||||
|
tabs.value = [...(tabs.value || []), tabMeta] |
||||||
|
activeTab.value = tabs.value.length - 1 |
||||||
|
} |
||||||
|
const clearTabs = () => { |
||||||
|
tabs.value = [] |
||||||
|
} |
||||||
|
|
||||||
|
return {tabs, addTab, activeTab, clearTabs} |
||||||
|
} |
@ -0,0 +1,32 @@ |
|||||||
|
import {store} from 'nuxt3-store' |
||||||
|
import {Api} from "nocodb-sdk"; |
||||||
|
import {useNuxtApp} from "#app"; |
||||||
|
|
||||||
|
export const useUser = () =>{ |
||||||
|
const user = store({ |
||||||
|
name: 'user', |
||||||
|
type: 'localstorage', |
||||||
|
value: {token: null, user : null}, |
||||||
|
reactiveType: 'reactive', |
||||||
|
version: '1.0.0' |
||||||
|
}) |
||||||
|
|
||||||
|
const {$api}: { $api: Api<any> } = useNuxtApp() as any |
||||||
|
|
||||||
|
|
||||||
|
const getUser =async (args = {}) => { |
||||||
|
const userInfo = await $api.auth.me(args, { |
||||||
|
headers: { |
||||||
|
'xc-auth': user.value.token |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
user.user = userInfo |
||||||
|
} |
||||||
|
|
||||||
|
const setToken = (token) => { |
||||||
|
user.token = token |
||||||
|
} |
||||||
|
|
||||||
|
return {user,setToken, getUser} |
||||||
|
} |
@ -0,0 +1,14 @@ |
|||||||
|
export async function extractSdkResponseErrorMsg(e:Error & {response:any}) { |
||||||
|
if (!e || !e.response) { return e.message } |
||||||
|
let msg |
||||||
|
if (e.response.data instanceof Blob) { |
||||||
|
try { |
||||||
|
msg = JSON.parse(await e.response.data.text()).msg |
||||||
|
} catch { |
||||||
|
msg = 'Some internal error occurred' |
||||||
|
} |
||||||
|
} else { |
||||||
|
msg = e.response.data.msg || e.response.data.message || 'Some internal error occurred' |
||||||
|
} |
||||||
|
return msg || 'Some error occurred' |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
<template> |
||||||
|
<div class=""> |
||||||
|
<!-- <div class="topbar">--> |
||||||
|
<!-- </div>--> |
||||||
|
<!-- <div class="sidebar">--> |
||||||
|
<!-- </div>--> |
||||||
|
<!-- <div class="content">--> |
||||||
|
<slot></slot> |
||||||
|
<!-- </div>--> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
name: "default" |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped> |
||||||
|
|
||||||
|
</style> |
@ -0,0 +1,35 @@ |
|||||||
|
import {defineNuxtConfig} from 'nuxt' |
||||||
|
|
||||||
|
// https://v3.nuxtjs.org/api/configuration/nuxt.config
|
||||||
|
export default defineNuxtConfig({ |
||||||
|
// modules: ['@nuxtjs/tailwindcss'],
|
||||||
|
// buildModules: [
|
||||||
|
// 'nuxt-vite'
|
||||||
|
// ],
|
||||||
|
modules: ['nuxt3-store'], |
||||||
|
ssr:false, |
||||||
|
plugins: [ |
||||||
|
// '~/plugins/vuetify.ts',
|
||||||
|
// '~/plugins/api.ts',
|
||||||
|
], |
||||||
|
// css: ['vuetify/lib/styles/main.sass'],
|
||||||
|
// build: {
|
||||||
|
// transpile: ['vuetify']
|
||||||
|
// },
|
||||||
|
|
||||||
|
css: [ |
||||||
|
'primevue/resources/themes/saga-blue/theme.css', |
||||||
|
'primevue/resources/primevue.css', |
||||||
|
'primeicons/primeicons.css', |
||||||
|
'primeflex/primeflex.css', |
||||||
|
], |
||||||
|
build: { |
||||||
|
transpile: ['primevue'] |
||||||
|
}, |
||||||
|
|
||||||
|
vite: { |
||||||
|
define: { |
||||||
|
'process.env.DEBUG': 'false', |
||||||
|
} |
||||||
|
} |
||||||
|
}) |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,24 @@ |
|||||||
|
{ |
||||||
|
"private": true, |
||||||
|
"scripts": { |
||||||
|
"build": "nuxt build", |
||||||
|
"dev": "nuxt dev", |
||||||
|
"generate": "nuxt generate", |
||||||
|
"preview": "nuxt preview" |
||||||
|
}, |
||||||
|
"devDependencies": { |
||||||
|
"@nuxtjs/tailwindcss": "^5.1.2", |
||||||
|
"fibers": "^5.0.1", |
||||||
|
"nuxt": "3.0.0-rc.3", |
||||||
|
"sass": "^1.53.0", |
||||||
|
"sass-loader": "^10.3.0" |
||||||
|
}, |
||||||
|
"dependencies": { |
||||||
|
"nocodb-sdk": "file:../nocodb-sdk", |
||||||
|
"nuxt3-store": "^1.0.0", |
||||||
|
"vuetify": "^3.0.0-alpha.12", |
||||||
|
"primevue": "3.10.0", |
||||||
|
"primeflex": "3.2.0", |
||||||
|
"primeicons": "5.0.0" |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,67 @@ |
|||||||
|
<template> |
||||||
|
<!-- todo: move to layout or create a reusable component --> |
||||||
|
<div class="nc-container"> |
||||||
|
<div class="nc-topbar shadow-2"> |
||||||
|
</div> |
||||||
|
<div class="nc-sidebar shadow-2 p-4 overflow-y-auto"> |
||||||
|
<DashboardTreeView></DashboardTreeView> |
||||||
|
</div> |
||||||
|
<div class="nc-content p-4 overflow-auto"> |
||||||
|
<DashboardTabView></DashboardTabView> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup lang="ts"> |
||||||
|
import {useProject} from "~/composables/project"; |
||||||
|
import {watch} from "vue"; |
||||||
|
import {useTabs} from "~/composables/tabs"; |
||||||
|
|
||||||
|
const route = useRoute() |
||||||
|
const {loadProject, loadTables} = useProject() |
||||||
|
const {clearTabs} = useTabs() |
||||||
|
|
||||||
|
|
||||||
|
onMounted(async () => { |
||||||
|
await loadProject(route.params.projectId as string) |
||||||
|
await loadTables() |
||||||
|
}) |
||||||
|
|
||||||
|
watch(() => route.params.projectId, async (newVal, oldVal) => { |
||||||
|
if (newVal && newVal !== oldVal) { |
||||||
|
clearTabs() |
||||||
|
await loadProject(newVal as string) |
||||||
|
await loadTables() |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped lang="scss"> |
||||||
|
.nc-container { |
||||||
|
.nc-topbar { |
||||||
|
position: fixed; |
||||||
|
top: 0; |
||||||
|
left: 0; |
||||||
|
height: 50px; |
||||||
|
width: 100%; |
||||||
|
z-index: 5; |
||||||
|
} |
||||||
|
|
||||||
|
.nc-sidebar { |
||||||
|
position: fixed; |
||||||
|
top: 50px; |
||||||
|
left: 0; |
||||||
|
height: calc(100% - 50px); |
||||||
|
width: 250px; |
||||||
|
} |
||||||
|
|
||||||
|
.nc-content { |
||||||
|
position: fixed; |
||||||
|
top: 50px; |
||||||
|
left: 250px; |
||||||
|
height: calc(100% - 50px); |
||||||
|
width: calc(100% - 250px); |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,42 @@ |
|||||||
|
<template> |
||||||
|
<div class="container"> |
||||||
|
|
||||||
|
<Card style="width:500px"> |
||||||
|
<template #title> |
||||||
|
Signup |
||||||
|
</template> |
||||||
|
<template #content> |
||||||
|
<InputText type="text" v-model="value" label="Email"/> |
||||||
|
</template> |
||||||
|
<template #footer> |
||||||
|
<Button label="Small" icon="pi pi-check" class="p-button-sm" /> |
||||||
|
</template> |
||||||
|
</Card> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup lang="ts"> |
||||||
|
import { ref } from 'vue'; |
||||||
|
import { useToast } from "primevue/usetoast"; |
||||||
|
const text = ref(); |
||||||
|
const toast = useToast(); |
||||||
|
const greet = () => { |
||||||
|
toast.add({severity: 'info', summary: 'Hello ' + text.value}); |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss"> |
||||||
|
.container { |
||||||
|
margin: 0 auto; |
||||||
|
min-height: 100vh; |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
div { |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
align-items: center; |
||||||
|
margin-top: 1rem; |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,17 @@ |
|||||||
|
<template> |
||||||
|
<div class="container"> |
||||||
|
|
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup lang="ts"> |
||||||
|
import {useRouter} from "#app"; |
||||||
|
|
||||||
|
const $router = useRouter() |
||||||
|
|
||||||
|
$router.replace('/projects') |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss"> |
||||||
|
|
||||||
|
</style> |
@ -0,0 +1,88 @@ |
|||||||
|
<template> |
||||||
|
|
||||||
|
|
||||||
|
<!-- todo: move to layout or create a reusable component --> |
||||||
|
<div class="nc-container"> |
||||||
|
<div class="nc-topbar shadow-2"> |
||||||
|
</div> |
||||||
|
<div class="nc-sidebar shadow-2 p-4 overflow-y-auto"> |
||||||
|
|
||||||
|
</div> |
||||||
|
<div class="nc-content p-4 overflow-auto"> |
||||||
|
<div class="grid"> |
||||||
|
<div class="col-3 p-3" v-for="project in projects" :key="project.id"> |
||||||
|
|
||||||
|
<Card @click="navigateToDashboard(project)"> |
||||||
|
<template #content> |
||||||
|
<div class="text-center"> |
||||||
|
<h3>{{ project.title }}</h3> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
</Card> |
||||||
|
|
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup lang="ts"> |
||||||
|
|
||||||
|
import {useRouter} from "#app"; |
||||||
|
|
||||||
|
const {$api} = useNuxtApp() |
||||||
|
const {user} = useUser() |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const $router = useRouter() |
||||||
|
|
||||||
|
const projects = ref() |
||||||
|
|
||||||
|
const loadProjects = async () => { |
||||||
|
const projectsResponse = await $api.project.list({}, { |
||||||
|
headers: { |
||||||
|
'xc-auth': user.token |
||||||
|
} |
||||||
|
}) |
||||||
|
projects.value = projectsResponse.list |
||||||
|
} |
||||||
|
|
||||||
|
const navigateToDashboard = async (project) => { |
||||||
|
await $router.push('/dashboard/' + project.id) |
||||||
|
} |
||||||
|
|
||||||
|
onMounted(async () => { |
||||||
|
await loadProjects() |
||||||
|
}) |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped lang="scss"> |
||||||
|
.nc-container { |
||||||
|
.nc-topbar { |
||||||
|
position: fixed; |
||||||
|
top: 0; |
||||||
|
left: 0; |
||||||
|
height: 50px; |
||||||
|
width: 100%; |
||||||
|
z-index: 5; |
||||||
|
} |
||||||
|
|
||||||
|
.nc-sidebar { |
||||||
|
position: fixed; |
||||||
|
top: 50px; |
||||||
|
left: 0; |
||||||
|
height: calc(100% - 50px); |
||||||
|
width: 250px; |
||||||
|
} |
||||||
|
|
||||||
|
.nc-content { |
||||||
|
position: fixed; |
||||||
|
top: 50px; |
||||||
|
left: 250px; |
||||||
|
height: calc(100% - 50px); |
||||||
|
width: calc(100% - 250px); |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,18 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<Sidebar :visible="true" position="left" :dismissable="false"> |
||||||
|
Content |
||||||
|
|
||||||
|
</Sidebar> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
name: "dashboard" |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped> |
||||||
|
|
||||||
|
</style> |
@ -0,0 +1,65 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<!-- Enter your work email --> |
||||||
|
<Card class="p-4 mx-auto mt-5" style="max-width: 500px"> |
||||||
|
<template #content> |
||||||
|
|
||||||
|
<Message class="" v-if="error" severity="error">{{ error }}</Message> |
||||||
|
|
||||||
|
<div class="p-float-label mt-5"> |
||||||
|
<InputText id="email" type="text" v-model="form.email" style="width:100%"/> |
||||||
|
<label for="email">Email</label> |
||||||
|
</div> |
||||||
|
|
||||||
|
<!-- Enter your password --> |
||||||
|
<div class="p-float-label mt-5"> |
||||||
|
<InputText id="password" type="password" v-model="form.password" style="width:100%"/> |
||||||
|
<label for="password">Password</label> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="text-center"> |
||||||
|
<Button |
||||||
|
class="mt-5" |
||||||
|
@click="signIn" |
||||||
|
> |
||||||
|
<b>Sign In</b> |
||||||
|
</Button> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
</Card> |
||||||
|
</div> |
||||||
|
|
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup lang="ts"> |
||||||
|
import {ref, reactive} from 'vue' |
||||||
|
import {useUser} from "~/composables/user"; |
||||||
|
import {extractSdkResponseErrorMsg} from "~/helpers/errorUtils"; |
||||||
|
import {useNuxtApp, useRouter} from "#app"; |
||||||
|
|
||||||
|
const { $api} = useNuxtApp() |
||||||
|
const $router = useRouter() |
||||||
|
|
||||||
|
const valid = ref() |
||||||
|
const error = ref() |
||||||
|
const form = reactive({ |
||||||
|
email: '', |
||||||
|
password: '' |
||||||
|
}) |
||||||
|
const {user, setToken} = useUser() |
||||||
|
|
||||||
|
const signIn = async () => { |
||||||
|
error.value = null |
||||||
|
try { |
||||||
|
const {token} = await $api.auth.signin(form) |
||||||
|
await setToken(token) |
||||||
|
await $router.push('/projects') |
||||||
|
} catch (e) { |
||||||
|
error.value = await extractSdkResponseErrorMsg(e) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
</script> |
||||||
|
<style scoped> |
||||||
|
|
||||||
|
</style> |
@ -0,0 +1,62 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<!-- Enter your work email --> |
||||||
|
<Card class="p-4 mx-auto mt-5" style="max-width: 500px"> |
||||||
|
<template #content> |
||||||
|
|
||||||
|
<Message class="" v-if="error" severity="error">{{ error }}</Message> |
||||||
|
|
||||||
|
<div class="p-float-label mt-5"> |
||||||
|
<InputText id="email" type="text" v-model="form.email" style="width:100%"/> |
||||||
|
<label for="email">Email</label> |
||||||
|
</div> |
||||||
|
|
||||||
|
<!-- Enter your password --> |
||||||
|
<div class="p-float-label mt-5"> |
||||||
|
<InputText id="password" type="password" v-model="form.password" style="width:100%"/> |
||||||
|
<label for="password">Password</label> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="text-center"> |
||||||
|
<Button |
||||||
|
class="mt-5" |
||||||
|
@click="signUp" |
||||||
|
> |
||||||
|
<b>Sign Up</b> |
||||||
|
</Button> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
</Card> |
||||||
|
</div> |
||||||
|
|
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup lang="ts"> |
||||||
|
import {ref, reactive} from 'vue' |
||||||
|
import {useUser} from "~/composables/user"; |
||||||
|
import {extractSdkResponseErrorMsg} from "~/helpers/errorUtils"; |
||||||
|
|
||||||
|
const {$api, $router} = useNuxtApp() |
||||||
|
const valid = ref() |
||||||
|
const error = ref() |
||||||
|
const form = reactive({ |
||||||
|
email: '', |
||||||
|
password: '' |
||||||
|
}) |
||||||
|
const {user, setToken} = useUser() |
||||||
|
|
||||||
|
const signUp = async () => { |
||||||
|
error.value = null |
||||||
|
try { |
||||||
|
const {token} = await $api.auth.signup(form) |
||||||
|
await setToken(token) |
||||||
|
$router.push('/projects') |
||||||
|
} catch (e) { |
||||||
|
error.value = await extractSdkResponseErrorMsg(e) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
</script> |
||||||
|
<style scoped> |
||||||
|
|
||||||
|
</style> |
@ -0,0 +1,41 @@ |
|||||||
|
import { Api } from 'nocodb-sdk'; |
||||||
|
import {defineNuxtPlugin} from "nuxt3/app"; |
||||||
|
|
||||||
|
|
||||||
|
export default defineNuxtPlugin((nuxtApp) => { |
||||||
|
|
||||||
|
// Doing something with nuxtApp
|
||||||
|
|
||||||
|
const api = getApi(null, null) |
||||||
|
|
||||||
|
nuxtApp.provide('api', api) |
||||||
|
|
||||||
|
|
||||||
|
return { |
||||||
|
provide: { |
||||||
|
api123:api |
||||||
|
} |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
|
||||||
|
export function getApi($store, $axios) { |
||||||
|
const api = new Api({ |
||||||
|
baseURL: 'http://localhost:8080', |
||||||
|
headers: { |
||||||
|
'xc-auth': $store?.state?.users?.token |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
if($axios) { |
||||||
|
// overwrite with nuxt axios instance
|
||||||
|
api.instance = $axios |
||||||
|
} |
||||||
|
return api |
||||||
|
} |
||||||
|
//
|
||||||
|
// export default function({ store: $store, $axios, ...rest }, inject) {
|
||||||
|
// const api = getApi($store, $axios)
|
||||||
|
//
|
||||||
|
// inject('api', api)
|
||||||
|
// }
|
@ -0,0 +1,27 @@ |
|||||||
|
import {defineNuxtPlugin} from "#app"; |
||||||
|
import PrimeVue from "primevue/config"; |
||||||
|
import Button from "primevue/button"; |
||||||
|
import InputText from "primevue/inputtext"; |
||||||
|
import Toast from "primevue/toast"; |
||||||
|
import Card from "primevue/card"; |
||||||
|
import Sidebar from "primevue/sidebar"; |
||||||
|
import Message from "primevue/message"; |
||||||
|
import TabMenu from "primevue/tabmenu"; |
||||||
|
import DataTable from "primevue/datatable"; |
||||||
|
import Column from "primevue/column"; |
||||||
|
import ToastService from 'primevue/toastservice'; |
||||||
|
|
||||||
|
export default defineNuxtPlugin((nuxtApp) => { |
||||||
|
nuxtApp.vueApp.use(PrimeVue, {ripple: true}); |
||||||
|
nuxtApp.vueApp.use(ToastService); |
||||||
|
nuxtApp.vueApp.component('Button', Button); |
||||||
|
nuxtApp.vueApp.component('InputText', InputText); |
||||||
|
nuxtApp.vueApp.component('Toast', Toast); |
||||||
|
nuxtApp.vueApp.component('Card', Card); |
||||||
|
nuxtApp.vueApp.component('Sidebar', Sidebar); |
||||||
|
nuxtApp.vueApp.component('Message', Message); |
||||||
|
nuxtApp.vueApp.component('TabMenu', TabMenu); |
||||||
|
nuxtApp.vueApp.component('DataTable', DataTable); |
||||||
|
nuxtApp.vueApp.component('Column', Column); |
||||||
|
//other components that you need
|
||||||
|
}); |
@ -0,0 +1,21 @@ |
|||||||
|
import { createVuetify } from 'vuetify' |
||||||
|
import { |
||||||
|
VApp, |
||||||
|
VAppBar, |
||||||
|
VBtn |
||||||
|
} from 'vuetify/components' |
||||||
|
import {defineNuxtPlugin} from "nuxt/app"; |
||||||
|
|
||||||
|
// Import everything
|
||||||
|
// import * as components from 'vuetify/components'
|
||||||
|
|
||||||
|
export default defineNuxtPlugin((nuxtApp) => { |
||||||
|
// const vuetify = createVuetify({
|
||||||
|
// components/*: {
|
||||||
|
// VApp,
|
||||||
|
// VAppBar,
|
||||||
|
// VBtn*/
|
||||||
|
// // }
|
||||||
|
// })
|
||||||
|
// nuxtApp.vueApp.use(vuetify)
|
||||||
|
}) |
@ -0,0 +1,8 @@ |
|||||||
|
/** @type {import('tailwindcss').Config} */ |
||||||
|
module.exports = { |
||||||
|
content: [], |
||||||
|
theme: { |
||||||
|
extend: {}, |
||||||
|
}, |
||||||
|
plugins: [], |
||||||
|
} |
Loading…
Reference in new issue