project setup
This commit is contained in:
9
.env
Normal file
9
.env
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
VITE_FIREBASE_API_KEY=AIzaSyBxt-j-9yVwt-3iPLp1Px-a038ZXwAiHOs
|
||||||
|
VITE_FIREBASE_AUTH_DOMAIN=app.contexted.io
|
||||||
|
VITE_FIREBASE_DATABASE_URL=https://contexted-f8b4e.firebaseio.com
|
||||||
|
VITE_FIREBASE_PROJECT_ID=contexted-f8b4e
|
||||||
|
VITE_FIREBASE_STORAGE_BUCKET=contexted-f8b4e.appspot.com
|
||||||
|
VITE_FIREBASE_MESSAGE_SENDER_ID=1048273547256zz
|
||||||
|
VITE_FIREBASE_APP_ID=1:1048273547256:web:c5516617eeeabd470f700d
|
||||||
|
VITE_FIREBASE_MEASUREMENT_ID=G-ZMQXB5HFNV
|
||||||
|
VITE_MIXPANEL_API_TOKEN=786d5c92512f20e9de9eac97c65aed36
|
||||||
6
.prettierrc
Normal file
6
.prettierrc
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"tabWidth": 2,
|
||||||
|
"useTabs": false,
|
||||||
|
"semi": false,
|
||||||
|
"singleQuote": true
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
<title>Vite + Vue + TS</title>
|
<title>Vite + Vue + TS</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app" class="bg-light"></div>
|
||||||
<script type="module" src="/src/main.ts"></script>
|
<script type="module" src="/src/main.ts"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
3553
package-lock.json
generated
Normal file
3553
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -9,10 +9,15 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@popperjs/core": "^2.11.7",
|
||||||
|
"bootstrap": "^5.2.3",
|
||||||
|
"bootstrap-icons": "^1.10.5",
|
||||||
|
"firebase": "^9.20.0",
|
||||||
"vue": "^3.2.47"
|
"vue": "^3.2.47"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "^4.1.0",
|
"@vitejs/plugin-vue": "^4.1.0",
|
||||||
|
"sass": "^1.62.1",
|
||||||
"typescript": "^5.0.2",
|
"typescript": "^5.0.2",
|
||||||
"vite": "^4.3.2",
|
"vite": "^4.3.2",
|
||||||
"vue-tsc": "^1.4.2"
|
"vue-tsc": "^1.4.2"
|
||||||
|
|||||||
41
src/App.vue
41
src/App.vue
@@ -1,30 +1,23 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import HelloWorld from './components/HelloWorld.vue'
|
import TopBar from './components/TopBar.vue'
|
||||||
|
import SideBar from './components/SideBar.vue'
|
||||||
|
import useNotes from './composables/useNotes'
|
||||||
|
|
||||||
|
const { notes } = useNotes()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<TopBar />
|
||||||
<a href="https://vitejs.dev" target="_blank">
|
<div class="container g-3 d-flex h-100" style="padding-top: 50px">
|
||||||
<img src="/vite.svg" class="logo" alt="Vite logo" />
|
<SideBar class="py-3" />
|
||||||
</a>
|
<div id="main" class="bg-white border-start border-end px-4 py-3">
|
||||||
<a href="https://vuejs.org/" target="_blank">
|
main
|
||||||
<img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
|
<pre>{{ notes }}</pre>
|
||||||
</a>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<HelloWorld msg="Vite + Vue" />
|
|
||||||
</template>
|
</template>
|
||||||
|
<style>
|
||||||
<style scoped>
|
#main {
|
||||||
.logo {
|
overflow: auto;
|
||||||
height: 6em;
|
flex: 1 1 0;
|
||||||
padding: 1.5em;
|
}</style>
|
||||||
will-change: filter;
|
|
||||||
transition: filter 300ms;
|
|
||||||
}
|
|
||||||
.logo:hover {
|
|
||||||
filter: drop-shadow(0 0 2em #646cffaa);
|
|
||||||
}
|
|
||||||
.logo.vue:hover {
|
|
||||||
filter: drop-shadow(0 0 2em #42b883aa);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
9
src/assets/style.scss
Normal file
9
src/assets/style.scss
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
$primary: #1e4bc4;
|
||||||
|
|
||||||
|
@import 'bootstrap/scss/bootstrap';
|
||||||
|
|
||||||
|
body,
|
||||||
|
body > div,
|
||||||
|
html {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { ref } from 'vue'
|
|
||||||
|
|
||||||
defineProps<{ msg: string }>()
|
|
||||||
|
|
||||||
const count = ref(0)
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<h1>{{ msg }}</h1>
|
|
||||||
|
|
||||||
<div class="card">
|
|
||||||
<button type="button" @click="count++">count is {{ count }}</button>
|
|
||||||
<p>
|
|
||||||
Edit
|
|
||||||
<code>components/HelloWorld.vue</code> to test HMR
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Check out
|
|
||||||
<a href="https://vuejs.org/guide/quick-start.html#local" target="_blank"
|
|
||||||
>create-vue</a
|
|
||||||
>, the official Vue + Vite starter
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Install
|
|
||||||
<a href="https://github.com/vuejs/language-tools" target="_blank">Volar</a>
|
|
||||||
in your IDE for a better DX
|
|
||||||
</p>
|
|
||||||
<p class="read-the-docs">Click on the Vite and Vue logos to learn more</p>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.read-the-docs {
|
|
||||||
color: #888;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
48
src/components/SideBar.vue
Normal file
48
src/components/SideBar.vue
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import useNotes from '../composables/useNotes'
|
||||||
|
import SideBarMenu from './SideBar/SideBarMenu.vue'
|
||||||
|
import SideBarMenuItem from './SideBar/SideBarMenuItem.vue'
|
||||||
|
const { rootNote } = useNotes()
|
||||||
|
|
||||||
|
interface ViewMode {
|
||||||
|
name: string
|
||||||
|
icon: string
|
||||||
|
}
|
||||||
|
const viewModes: ViewMode[] = [
|
||||||
|
{ name: 'Note', icon: 'card-text' },
|
||||||
|
{ name: 'List', icon: 'list-task' },
|
||||||
|
{ name: 'Mindmap', icon: 'diagram-3' },
|
||||||
|
]
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div id="sidebar" class="position-relative pe-3 d-flex flex-column" style="width: 200px">
|
||||||
|
<SideBarMenu>
|
||||||
|
<template #header>Root note</template>
|
||||||
|
<template #items>
|
||||||
|
<SideBarMenuItem icon="house">{{
|
||||||
|
rootNote?.title
|
||||||
|
}}</SideBarMenuItem>
|
||||||
|
</template>
|
||||||
|
</SideBarMenu>
|
||||||
|
<SideBarMenu>
|
||||||
|
<template #header>View mode</template>
|
||||||
|
<template #items>
|
||||||
|
<SideBarMenuItem v-for="viewMode in viewModes" :icon="viewMode.icon">{{
|
||||||
|
viewMode.name
|
||||||
|
}}</SideBarMenuItem>
|
||||||
|
</template>
|
||||||
|
</SideBarMenu>
|
||||||
|
<SideBarMenu>
|
||||||
|
<template #header>Recent notes</template>
|
||||||
|
<template #items>
|
||||||
|
<SideBarMenuItem>{{ rootNote?.title }}</SideBarMenuItem>
|
||||||
|
</template>
|
||||||
|
</SideBarMenu>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<style lang="scss">
|
||||||
|
#sidebar {
|
||||||
|
gap: 1rem;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
13
src/components/SideBar/SideBarMenu.vue
Normal file
13
src/components/SideBar/SideBarMenu.vue
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="text-uppercase fw-semibold header">
|
||||||
|
<slot name="header"></slot>
|
||||||
|
</div>
|
||||||
|
<slot name="items"></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<style scoped>
|
||||||
|
.header {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
20
src/components/SideBar/SideBarMenuItem.vue
Normal file
20
src/components/SideBar/SideBarMenuItem.vue
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
const props = defineProps<{
|
||||||
|
icon?: string
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<a class="text-opacity-50 text-decoration-none w-100 d-block link-secondary">
|
||||||
|
<i :class="`bi bi-${props.icon}`" class="me-2" v-if="props.icon"></i
|
||||||
|
><slot></slot>
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
a {
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: var(--bs-border-radius);
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
background-color: var(--bs-gray-300);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
10
src/components/TopBar.vue
Normal file
10
src/components/TopBar.vue
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="bg-primary position-absolute top-0 start-0 end-0"
|
||||||
|
style="height: 50px"
|
||||||
|
>
|
||||||
|
<div class="container g-3 h-100 d-flex align-items-center text-white">
|
||||||
|
top bar
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
15
src/composables/useNotes.ts
Normal file
15
src/composables/useNotes.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { ref } from 'vue'
|
||||||
|
const notes = ref<Note[]>([])
|
||||||
|
|
||||||
|
export default function useNotes() {
|
||||||
|
const setDefaultNotes = (defaultNotes: Note[]) => {
|
||||||
|
notes.value = defaultNotes.map((note) => ({
|
||||||
|
...note,
|
||||||
|
created: new Date().getTime(),
|
||||||
|
modified: new Date().getTime(),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
const rootNote = notes.value.find((note) => note.isRoot)
|
||||||
|
|
||||||
|
return { notes, setDefaultNotes, rootNote }
|
||||||
|
}
|
||||||
17
src/global.d.ts
vendored
Normal file
17
src/global.d.ts
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
declare global {
|
||||||
|
interface Note {
|
||||||
|
id?: string
|
||||||
|
title: string
|
||||||
|
content: string
|
||||||
|
created: number
|
||||||
|
modified: number
|
||||||
|
isRoot: boolean
|
||||||
|
wordCount?: number
|
||||||
|
links?: {
|
||||||
|
to: string[]
|
||||||
|
from: string[]
|
||||||
|
}
|
||||||
|
isRoot?: boolean
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export {}
|
||||||
@@ -1,5 +1,10 @@
|
|||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import './style.css'
|
import './assets/style.scss'
|
||||||
|
import 'bootstrap-icons/font/bootstrap-icons.css'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
|
import useNotes from './composables/useNotes'
|
||||||
|
import { defaultNotes } from './utils/defaultNotes'
|
||||||
|
const { setDefaultNotes } = useNotes()
|
||||||
|
setDefaultNotes(defaultNotes)
|
||||||
|
|
||||||
createApp(App).mount('#app')
|
createApp(App).mount('#app')
|
||||||
|
|||||||
@@ -1,80 +0,0 @@
|
|||||||
:root {
|
|
||||||
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
|
||||||
line-height: 1.5;
|
|
||||||
font-weight: 400;
|
|
||||||
|
|
||||||
color-scheme: light dark;
|
|
||||||
color: rgba(255, 255, 255, 0.87);
|
|
||||||
background-color: #242424;
|
|
||||||
|
|
||||||
font-synthesis: none;
|
|
||||||
text-rendering: optimizeLegibility;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
-webkit-text-size-adjust: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
font-weight: 500;
|
|
||||||
color: #646cff;
|
|
||||||
text-decoration: inherit;
|
|
||||||
}
|
|
||||||
a:hover {
|
|
||||||
color: #535bf2;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
display: flex;
|
|
||||||
place-items: center;
|
|
||||||
min-width: 320px;
|
|
||||||
min-height: 100vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 3.2em;
|
|
||||||
line-height: 1.1;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
border-radius: 8px;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
padding: 0.6em 1.2em;
|
|
||||||
font-size: 1em;
|
|
||||||
font-weight: 500;
|
|
||||||
font-family: inherit;
|
|
||||||
background-color: #1a1a1a;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: border-color 0.25s;
|
|
||||||
}
|
|
||||||
button:hover {
|
|
||||||
border-color: #646cff;
|
|
||||||
}
|
|
||||||
button:focus,
|
|
||||||
button:focus-visible {
|
|
||||||
outline: 4px auto -webkit-focus-ring-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
padding: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#app {
|
|
||||||
max-width: 1280px;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 2rem;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: light) {
|
|
||||||
:root {
|
|
||||||
color: #213547;
|
|
||||||
background-color: #ffffff;
|
|
||||||
}
|
|
||||||
a:hover {
|
|
||||||
color: #747bff;
|
|
||||||
}
|
|
||||||
button {
|
|
||||||
background-color: #f9f9f9;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
20
src/utils/defaultNotes.ts
Normal file
20
src/utils/defaultNotes.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
export const defaultNotes: Note[] = [
|
||||||
|
{
|
||||||
|
isRoot: true,
|
||||||
|
title: 'Your first note',
|
||||||
|
content: `Contexted is a **relational note-taking app**. Use it as your personal knowledge base, research assistent or just to map out thoughts.\n\n
|
||||||
|
### **How does it work?**
|
||||||
|
* Create a new note by typing words between [[brackets]]
|
||||||
|
* Click on **Mindmap mode** in the menu left to visualize your notes
|
||||||
|
\n
|
||||||
|
Let's get started!`,
|
||||||
|
created: 0,
|
||||||
|
modified: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'brackets',
|
||||||
|
content: `If you type square brackets around text a link is created automatically. Like magic!`,
|
||||||
|
created: 0,
|
||||||
|
modified: 0,
|
||||||
|
},
|
||||||
|
]
|
||||||
15
src/utils/firebase.ts
Normal file
15
src/utils/firebase.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { initializeApp } from 'firebase/app'
|
||||||
|
|
||||||
|
// TODO: Replace the following with your app's Firebase project configuration
|
||||||
|
const firebaseConfig: any = {
|
||||||
|
apiKey: import.meta.env.VUE_APP_FIREBASE_API_KEY,
|
||||||
|
authDomain: import.meta.env.VUE_APP_FIREBASE_AUTH_DOMAIN,
|
||||||
|
databaseURL: import.meta.env.VUE_APP_FIREBASE_DATABASE_URL,
|
||||||
|
projectId: import.meta.env.VUE_APP_FIREBASE_PROJECT_ID,
|
||||||
|
storageBucket: import.meta.env.VUE_APP_FIREBASE_STORAGE_BUCKET,
|
||||||
|
messagingSenderId: import.meta.env.VUE_APP_FIREBASE_MESSAGE_SENDER_ID,
|
||||||
|
appId: import.meta.env.VUE_APP_FIREBASE_APP_ID,
|
||||||
|
measurementId: import.meta.env.VUE_APP_FIREBASE_MEASUREMENT_ID,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const app = initializeApp(firebaseConfig)
|
||||||
Reference in New Issue
Block a user