Merge branch 'main' of github.com:lite-note/lite-note into main

This commit is contained in:
2021-05-13 16:27:06 +02:00
24 changed files with 338 additions and 340 deletions

View File

@@ -7,6 +7,8 @@ module.exports = {
'plugin:vue/vue3-essential', 'plugin:vue/vue3-essential',
'eslint:recommended', 'eslint:recommended',
'plugin:vue/recommended', 'plugin:vue/recommended',
'@vue/typescript/recommended',
'@vue/prettier/@typescript-eslint',
'plugin:prettier-vue/recommended' 'plugin:prettier-vue/recommended'
], ],
parserOptions: { parserOptions: {
@@ -17,7 +19,6 @@ module.exports = {
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off', '@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/camelcase': 'off', '@typescript-eslint/camelcase': 'off',
'vue/no-multiple-template-root': 'off',
'prettier-vue/prettier': [ 'prettier-vue/prettier': [
'error', 'error',
{ {

View File

@@ -155,6 +155,16 @@ $header-height: 40px;
color: var(--font-color); color: var(--font-color);
} }
table {
color: var(--font-color);
background-color: var(--background-color);
thead {
th {
color: var(--font-color);
}
}
}
blockquote { blockquote {
background-color: var(--background-color); background-color: var(--background-color);
} }

View File

@@ -1,53 +1,53 @@
<template> <template>
<header class="header-note"> <header class="header-note">
<router-link <router-link
:to="{ name: 'Home' }" :to="{ name: 'Home' }"
class="button is-small is-white back-button" class="button is-small is-white back-button"
> >
<img src="@/assets/icons/dark-left-arrow.svg" alt="go back left arrow" /> <img src="@/assets/icons/dark-left-arrow.svg" alt="go back left arrow" />
</router-link> </router-link>
<router-link <router-link
class="special-folder" class="special-folder"
:to="{ name: 'DraftNotes', params: { user, repo } }" :to="{ name: 'DraftNotes', params: { user, repo } }"
> >
draft draft
</router-link> </router-link>
<router-link <router-link
class="special-folder" class="special-folder"
:to="{ name: 'FleetingNotes', params: { user, repo } }" :to="{ name: 'FleetingNotes', params: { user, repo } }"
> >
inbox inbox
</router-link> </router-link>
</header> </header>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue' import { defineComponent } from 'vue'
export default defineComponent({ export default defineComponent({
name: 'HeaderNote', name: 'HeaderNote',
props: { props: {
user: { type: String, required: true }, user: { type: String, required: true },
repo: { type: String, required: true } repo: { type: String, required: true }
} }
}) })
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.header-note { .header-note {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
margin-top: 10px; margin-top: 10px;
.special-folder { .special-folder {
text-align: center; text-align: center;
} }
img { img {
&:hover { &:hover {
cursor: pointer; cursor: pointer;
} }
} }
} }
</style> </style>

View File

@@ -1,5 +1,5 @@
<template> <template>
<aside class="new-version" v-if="hasNewVersion"> <aside v-if="hasNewVersion" class="new-version">
<button class="button is-primary" @click="reload"> <button class="button is-primary" @click="reload">
new version available new version available
</button> </button>

View File

@@ -12,7 +12,7 @@
{{ displayedTitle }} {{ displayedTitle }}
</a> </a>
</div> </div>
<div class="share" v-if="false"> <div v-if="false" class="share">
<router-link <router-link
:to="{ :to="{
name: 'ShareNotes', name: 'ShareNotes',

View File

@@ -20,7 +20,7 @@
</div> </div>
<div class="column"> <div class="column">
<p> <p>
<router-link :to="{ name: 'RepoList' }" v-if="isLogged" <router-link v-if="isLogged" :to="{ name: 'RepoList' }"
>Manage your repos</router-link >Manage your repos</router-link
> >
</p> </p>
@@ -49,17 +49,15 @@
<form @submit.prevent> <form @submit.prevent>
<div class="columns is-centered is-vcentered to-user-repo"> <div class="columns is-centered is-vcentered to-user-repo">
<div class="column"> <div class="column">https://github.com/</div>
https://github.com/
</div>
<div class="columns column is-mobile is-centered is-vcentered"> <div class="columns column is-mobile is-centered is-vcentered">
<div class="column"> <div class="column">
<div class="field"> <div class="field">
<div class="control"> <div class="control">
<input <input
v-model="userInput"
class="input" class="input"
type="text" type="text"
v-model="userInput"
placeholder="user" placeholder="user"
/> />
</div> </div>
@@ -70,9 +68,9 @@
<div class="field"> <div class="field">
<div class="control"> <div class="control">
<input <input
v-model="repoInput"
class="input" class="input"
type="text" type="text"
v-model="repoInput"
placeholder="repo" placeholder="repo"
/> />
</div> </div>
@@ -109,8 +107,8 @@ import { useFavoriteRepos } from '@/modules/repo/hooks/useFavoriteRepos.hook'
import SignInGithub from '@/components/SignInGithub.vue' import SignInGithub from '@/components/SignInGithub.vue'
export default defineComponent({ export default defineComponent({
components: { SignInGithub },
name: 'WelcomeWord', name: 'WelcomeWord',
components: { SignInGithub },
setup() { setup() {
const { isLogged, username } = useGitHubLogin() const { isLogged, username } = useGitHubLogin()
const { savedFavoriteRepos } = useFavoriteRepos() const { savedFavoriteRepos } = useFavoriteRepos()

View File

@@ -1,33 +1,33 @@
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import { confirmMessage } from '@/utils/notif' import { confirmMessage } from '@/utils/notif'
import { GithubToken } from '@/modules/user/interfaces/GithubToken'
import { getAccessToken, saveAccessToken } from '@/modules/user/service/signIn' import { getAccessToken, saveAccessToken } from '@/modules/user/service/signIn'
import { GithubToken } from '@/modules/user/interfaces/GithubToken'
const username = ref<string | null>(null) const username = ref<string | null>(null)
const accessToken = ref<string | null>(null) const accessToken = ref<string | null>(null)
let init = true let init = true
export const useGitHubLogin = () => { const saveAccessTokenToLocal = async () => {
const saveAccessTokenToLocal = async () => { const response = await getAccessToken()
const response = await getAccessToken() username.value = response?.username || ''
username.value = response?.username || '' accessToken.value = response?.token || ''
accessToken.value = response?.token || '' }
}
const saveCredentials = async (token: GithubToken): Promise<void> => {
const accessToken = await saveAccessToken(token)
await saveAccessTokenToLocal()
confirmMessage(`${accessToken.username} is logged in!`)
}
export const useGitHubLogin = () => {
if (init) { if (init) {
init = false init = false
saveAccessTokenToLocal() saveAccessTokenToLocal()
} }
const saveCredentials = async (githubToken: GithubToken) => {
const accessToken = await saveAccessToken(githubToken)
await saveAccessTokenToLocal()
confirmMessage(`${accessToken.username} is logged in!`)
}
return { return {
isLogged: !!accessToken.value, isLogged: !!accessToken.value,
isReady: computed(() => accessToken.value !== null), isReady: computed(() => accessToken.value !== null),

View File

@@ -13,7 +13,7 @@ const md = new MarkdownIt({
h4: ['title', 'is-5'], h4: ['title', 'is-5'],
h5: ['title', 'is-6'], h5: ['title', 'is-6'],
h6: ['title', 'is-6'], h6: ['title', 'is-6'],
table: ['table', 'is-striped', 'is-hoverable'] table: ['table', 'is-fullwidth']
}) })
.use(blockEmbedPlugin, { .use(blockEmbedPlugin, {
youtube: { youtube: {

View File

@@ -100,8 +100,9 @@ export const useNote = (containerClass: string) => {
if (isMobile.value) { if (isMobile.value) {
container.style.height = `${(stackedNotes.value.length + 1) * 100}vh` container.style.height = `${(stackedNotes.value.length + 1) * 100}vh`
} else { } else {
container.style.width = `${NOTE_WIDTH * container.style.width = `${
(stackedNotes.value.length + 1)}px` NOTE_WIDTH * (stackedNotes.value.length + 1)
}px`
} }
} }

View File

@@ -39,10 +39,9 @@ export const useNoteOverlay = (className: string, index: number) => {
) as NodeListOf<HTMLElement> ) as NodeListOf<HTMLElement>
stackedNoteContainers.forEach((stackedNote, ind) => { stackedNoteContainers.forEach((stackedNote, ind) => {
stackedNote.style.right = `calc(-${NOTE_WIDTH}px + ${(stackedNotes.value stackedNote.style.right = `calc(-${NOTE_WIDTH}px + ${
.length - (stackedNotes.value.length - ind) * BOOKMARK_WIDTH
ind) * }rem)`
BOOKMARK_WIDTH}rem)`
}) })
} }
}) })

View File

@@ -13,8 +13,4 @@ const i18n = createI18n({
messages messages
}) })
createApp(App) createApp(App).use(router).use(i18n).use(createPinia()).mount('#app')
.use(router)
.use(i18n)
.use(createPinia())
.mount('#app')

View File

@@ -1,32 +1,32 @@
import { useUserRepoStore } from '@/modules/repo/store/userRepo.store' import { useUserRepoStore } from '@/modules/repo/store/userRepo.store'
import { computed } from 'vue' import { computed } from 'vue'
export const useFolderNotes = (folders: string[]) => { export const useFolderNotes = (folders: string[]) => {
const store = useUserRepoStore() const store = useUserRepoStore()
const fleetingNotes = computed(() => const fleetingNotes = computed(() =>
store.files.filter( store.files.filter(
(file) => (file) =>
folders.some((folder) => file.path?.startsWith(folder)) && folders.some((folder) => file.path?.startsWith(folder)) &&
file.path?.endsWith('.md') file.path?.endsWith('.md')
) )
) )
const content = computed(() => const content = computed(() =>
fleetingNotes.value?.length > 0 fleetingNotes.value?.length > 0
? fleetingNotes.value ? fleetingNotes.value
.map((note) => { .map((note) => {
const firstFolder = note.path?.split('/').shift() const firstFolder = note.path?.split('/').shift()
return `- [${note.path?.replace(`${firstFolder}/`, '')}](${ return `- [${note.path?.replace(`${firstFolder}/`, '')}](${
note.path note.path
})` })`
}) })
.join('\n') .join('\n')
: '' : ''
) )
return { return {
content content
} }
} }

View File

@@ -1,31 +1,31 @@
import { data } from '@/data/data' import { data } from '@/data/data'
import { DataType } from '@/data/DataType.enum' import { DataType } from '@/data/DataType.enum'
import { Note } from '@/modules/note/models/Note' import { Note } from '@/modules/note/models/Note'
import { useAsyncState } from '@vueuse/core' import { useAsyncState } from '@vueuse/core'
import { computed } from 'vue' import { computed } from 'vue'
export const useNoteCache = (sha: string) => { export const useNoteCache = (sha: string) => {
const noteId = computed(() => data.generateId(DataType.Note, sha)) const noteId = computed(() => data.generateId(DataType.Note, sha))
const getCachedNote = async () => data.get<DataType.Note, Note>(noteId.value) const getCachedNote = async () => data.get<DataType.Note, Note>(noteId.value)
const cachedNote = useAsyncState(getCachedNote, null) const cachedNote = useAsyncState(getCachedNote, null)
const saveCacheNote = async (content: string) => { const saveCacheNote = async (content: string) => {
const newNote: Note = { const newNote: Note = {
_id: noteId.value, _id: noteId.value,
$type: DataType.Note, $type: DataType.Note,
content content
} }
await data.update(newNote) await data.update(newNote)
await cachedNote.execute() await cachedNote.execute()
} }
return { return {
cachedNote: cachedNote.state, cachedNote: cachedNote.state,
isReady: cachedNote.isReady, isReady: cachedNote.isReady,
getCachedNote, getCachedNote,
saveCacheNote saveCacheNote
} }
} }

View File

@@ -1,6 +1,6 @@
import { DataType } from '@/data/DataType.enum' import { DataType } from '@/data/DataType.enum'
import { Model } from '@/data/models/Model' import { Model } from '@/data/models/Model'
export interface Note extends Model<DataType.Note> { export interface Note extends Model<DataType.Note> {
content: string content: string
} }

View File

@@ -1,32 +1,32 @@
const sanitizePath = (path: string) => { const sanitizePath = (path: string) => {
if (path.startsWith('./')) { if (path.startsWith('./')) {
return decodeURIComponent(path.replace('./', '')) return decodeURIComponent(path.replace('./', ''))
} }
return decodeURIComponent(path) return decodeURIComponent(path)
} }
const removeNoteFilename = (pathNote: string) => { const removeNoteFilename = (pathNote: string) => {
const path = pathNote.split('/') const path = pathNote.split('/')
path.pop() path.pop()
return sanitizePath(path.join('/')) return sanitizePath(path.join('/'))
} }
export const resolvePath = ( export const resolvePath = (
currentAbsolutePathNote: string, currentAbsolutePathNote: string,
pathToResolve: string pathToResolve: string
) => { ) => {
let currentAbsolutePath = removeNoteFilename(currentAbsolutePathNote) let currentAbsolutePath = removeNoteFilename(currentAbsolutePathNote)
pathToResolve = sanitizePath(pathToResolve) pathToResolve = sanitizePath(pathToResolve)
while (pathToResolve.startsWith('../')) { while (pathToResolve.startsWith('../')) {
const adjustedAbsolutePath = currentAbsolutePath.split('/') const adjustedAbsolutePath = currentAbsolutePath.split('/')
adjustedAbsolutePath.pop() adjustedAbsolutePath.pop()
currentAbsolutePath = adjustedAbsolutePath.join('/') currentAbsolutePath = adjustedAbsolutePath.join('/')
pathToResolve = pathToResolve.replace('../', '') pathToResolve = pathToResolve.replace('../', '')
} }
return currentAbsolutePath return currentAbsolutePath
? `${currentAbsolutePath}/${pathToResolve}` ? `${currentAbsolutePath}/${pathToResolve}`
: pathToResolve : pathToResolve
} }

View File

@@ -5,7 +5,6 @@ import {
getMainReadme, getMainReadme,
getUserSettingsContent getUserSettingsContent
} from '@/modules/repo/services/repo' } from '@/modules/repo/services/repo'
import { refreshToken } from '@/modules/user/service/signIn'
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
interface State { interface State {
@@ -29,7 +28,6 @@ export const useUserRepoStore = defineStore({
async setUserRepo(newUser: string, newRepo: string) { async setUserRepo(newUser: string, newRepo: string) {
this.user = newUser this.user = newUser
this.repo = newRepo this.repo = newRepo
await refreshToken()
const [readme, files] = await Promise.all([ const [readme, files] = await Promise.all([
getMainReadme(newUser, newRepo), getMainReadme(newUser, newRepo),
getFiles(newUser, newRepo) getFiles(newUser, newRepo)

View File

@@ -58,8 +58,6 @@ export const refreshToken = async () => {
| GithubToken | GithubToken
| GithubTokenError | GithubTokenError
console.log(githubToken)
if ('error' in githubToken) { if ('error' in githubToken) {
return null return null
} }
@@ -105,8 +103,6 @@ export const saveAccessToken = async (githubToken: GithubToken) => {
username: '' username: ''
} }
console.log(accessToken)
const octokit = new Octokit({ const octokit = new Octokit({
auth: accessToken?.token auth: accessToken?.token
}) })

View File

@@ -1,47 +1,45 @@
<template> <template>
<div class="draft-notes"> <div class="draft-notes">
<flux-note :user="user" :repo="repo" :content="content" key="draft-notes"> <flux-note key="draft-notes" :user="user" :repo="repo" :content="content">
<h3 class="subtitle is-3"> <h3 class="subtitle is-3">Drafts</h3>
Drafts </flux-note>
</h3> </div>
</flux-note> </template>
</div>
</template> <script lang="ts">
import { useFolderNotes } from '@/modules/note/hooks/useFolderNotes'
<script lang="ts"> import { defineAsyncComponent, defineComponent } from 'vue'
import { useFolderNotes } from '@/modules/note/hooks/useFolderNotes'
import { defineAsyncComponent, defineComponent } from 'vue' const FluxNote = defineAsyncComponent(() => import('@/components/FluxNote.vue'))
const FluxNote = defineAsyncComponent(() => import('@/components/FluxNote.vue')) const DRAFT_FOLDER = ['drafts', '_drafts']
const DRAFT_FOLDER = ['drafts', '_drafts'] export default defineComponent({
name: 'DraftNotes',
export default defineComponent({ components: {
name: 'DraftNotes', FluxNote
components: { },
FluxNote props: {
}, user: { type: String, required: true },
props: { repo: { type: String, required: true }
user: { type: String, required: true }, },
repo: { type: String, required: true } setup() {
}, const { content } = useFolderNotes(DRAFT_FOLDER)
setup() {
const { content } = useFolderNotes(DRAFT_FOLDER) return {
content
return { }
content }
} })
} </script>
})
</script> <style scoped lang="scss">
.draft-notes {
<style scoped lang="scss"> display: flex;
.draft-notes { flex: 1;
display: flex;
flex: 1; .subtitle {
text-align: center;
.subtitle { }
text-align: center; }
} </style>
}
</style>

View File

@@ -1,52 +1,50 @@
<template> <template>
<div class="fleeting-notes"> <div class="fleeting-notes">
<flux-note <flux-note
:user="user" key="fleeting-notes"
:repo="repo" :user="user"
:content="content" :repo="repo"
key="fleeting-notes" :content="content"
> >
<h3 class="subtitle is-3"> <h3 class="subtitle is-3">Inbox</h3>
Inbox </flux-note>
</h3> </div>
</flux-note> </template>
</div>
</template> <script lang="ts">
import { useFolderNotes } from '@/modules/note/hooks/useFolderNotes'
<script lang="ts"> import { defineAsyncComponent, defineComponent } from 'vue'
import { useFolderNotes } from '@/modules/note/hooks/useFolderNotes'
import { defineAsyncComponent, defineComponent } from 'vue' const FluxNote = defineAsyncComponent(() => import('@/components/FluxNote.vue'))
const FluxNote = defineAsyncComponent(() => import('@/components/FluxNote.vue')) const FLEETING_NOTES_FOLDER = ['inbox', '_inbox']
const FLEETING_NOTES_FOLDER = ['inbox', '_inbox'] export default defineComponent({
name: 'FleetingNotes',
export default defineComponent({ components: {
name: 'FleetingNotes', FluxNote
components: { },
FluxNote props: {
}, user: { type: String, required: true },
props: { repo: { type: String, required: true }
user: { type: String, required: true }, },
repo: { type: String, required: true } setup() {
}, const { content } = useFolderNotes(FLEETING_NOTES_FOLDER)
setup() {
const { content } = useFolderNotes(FLEETING_NOTES_FOLDER) return {
content
return { }
content }
} })
} </script>
})
</script> <style scoped lang="scss">
.fleeting-notes {
<style scoped lang="scss"> display: flex;
.fleeting-notes { flex: 1;
display: flex;
flex: 1; .subtitle {
text-align: center;
.subtitle { }
text-align: center; }
} </style>
}
</style>

View File

@@ -34,6 +34,9 @@ export default defineComponent({
}, },
setup(props) { setup(props) {
const { resetStackedNotes } = useQueryStackedNotes() const { resetStackedNotes } = useQueryStackedNotes()
onMounted(() => {
refreshToken()
})
onMounted(() => { onMounted(() => {
refreshToken() refreshToken()

View File

@@ -13,10 +13,10 @@
<div class="field-body"> <div class="field-body">
<div class="control"> <div class="control">
<input <input
v-model="user"
class="input" class="input"
type="text" type="text"
placeholder="GitHub username" placeholder="GitHub username"
v-model="user"
/> />
</div> </div>
</div> </div>
@@ -28,10 +28,10 @@
<div class="field-body"> <div class="field-body">
<div class="control"> <div class="control">
<input <input
v-model="token"
class="input" class="input"
type="password" type="password"
placeholder="Personal Access Token" placeholder="Personal Access Token"
v-model="token"
/> />
</div> </div>
</div> </div>

View File

@@ -6,8 +6,8 @@
<div v-else class="columns is-centered"> <div v-else class="columns is-centered">
<div class="column is-one-third"> <div class="column is-one-third">
<table <table
class="table is-striped is-hoverable"
v-if="favoriteRepos.length > 0" v-if="favoriteRepos.length > 0"
class="table is-striped is-hoverable"
> >
<thead> <thead>
<tr> <tr>

View File

@@ -6,10 +6,10 @@
</div> </div>
</article> </article>
<flux-note <flux-note
key="share-notes"
:user="user" :user="user"
:repo="repo" :repo="repo"
:content="content" :content="content"
key="share-notes"
:with-header="false" :with-header="false"
/> />
</div> </div>

View File

@@ -1,41 +1,41 @@
import { resolvePath } from '@/modules/repo/services/resolvePath' import { resolvePath } from '@/modules/repo/services/resolvePath'
describe('resolve path service', () => { describe('resolve path service', () => {
it('set the absolute path if path to resolve is empty', () => { it('set the absolute path if path to resolve is empty', () => {
expect(resolvePath('standard/README.md', '')).toEqual('standard/') expect(resolvePath('standard/README.md', '')).toEqual('standard/')
}) })
it('returns the path sanitized if there is no absolute path', () => { it('returns the path sanitized if there is no absolute path', () => {
expect(resolvePath('', './here/note.md')).toEqual('here/note.md') expect(resolvePath('', './here/note.md')).toEqual('here/note.md')
}) })
it('set the absolute path from the current path', () => { it('set the absolute path from the current path', () => {
expect(resolvePath('standard/README.md', './other-note.md')).toEqual( expect(resolvePath('standard/README.md', './other-note.md')).toEqual(
'standard/other-note.md' 'standard/other-note.md'
) )
}) })
it('set the absolute path from the current path with multiple level', () => { it('set the absolute path from the current path with multiple level', () => {
expect( expect(
resolvePath('standard/you/are/here/README.md', './other-note.md') resolvePath('standard/you/are/here/README.md', './other-note.md')
).toEqual('standard/you/are/here/other-note.md') ).toEqual('standard/you/are/here/other-note.md')
}) })
it('set the absolute path from the current path with a go back in the relative path', () => { it('set the absolute path from the current path with a go back in the relative path', () => {
expect( expect(
resolvePath('standard/you/are/here/README.md', '../other-note.md') resolvePath('standard/you/are/here/README.md', '../other-note.md')
).toEqual('standard/you/are/other-note.md') ).toEqual('standard/you/are/other-note.md')
expect( expect(
resolvePath('standard/you/are/here/README.md', '../../other-note.md') resolvePath('standard/you/are/here/README.md', '../../other-note.md')
).toEqual('standard/you/other-note.md') ).toEqual('standard/you/other-note.md')
expect( expect(
resolvePath('standard/you/are/here/README.md', './../../other-note.md') resolvePath('standard/you/are/here/README.md', './../../other-note.md')
).toEqual('standard/you/other-note.md') ).toEqual('standard/you/other-note.md')
expect( expect(
resolvePath('standard/you/are/here/README.md', './../../../other-note.md') resolvePath('standard/you/are/here/README.md', './../../../other-note.md')
).toEqual('standard/other-note.md') ).toEqual('standard/other-note.md')
}) })
}) })