-
Notifications
You must be signed in to change notification settings - Fork 45
[Work in progress] Separation of concerns using Vue #121
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
805614a
d17cdf1
8e97fbb
184f839
9680a9a
0e6d4ac
022d49c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,9 @@ | ||
| { | ||
| "presets": [ | ||
| "@babel/preset-env", | ||
| "@babel/preset-typescript" | ||
| ], | ||
| "@babel/preset-typescript", | ||
| ["vue", { | ||
| "eventModifiers": false | ||
| }] | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,3 @@ | ||
| dist | ||
| node_modules | ||
| typings/rdflib |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| <template> | ||
| <div id="MarkdownApp"> | ||
| <div v-if="isLoading">LOADING</div> | ||
| <MarkdownView v-if="isRendering" v-bind:markdown="markdown" v-on:edit="toggle" /> | ||
| <MarkdownEdit v-if="isEditing" v-bind:markdown="markdown" v-on:save="toggle" /> | ||
| </div> | ||
| </template> | ||
|
|
||
| <script lang="ts"> | ||
| import { Component, Prop, Vue } from 'vue-property-decorator'; | ||
| import MarkdownView from './components/MarkdownView.vue' | ||
| import { NamedNode } from 'rdflib' | ||
| import { loadMarkdown, saveMarkdown, STATE } from './markdown.service' | ||
| import MarkdownEdit from './components/MarkdownEdit.vue' | ||
|
|
||
| @Component({ | ||
| components: { | ||
| MarkdownEdit, | ||
| MarkdownView | ||
| } | ||
| }) | ||
| export default class App extends Vue { | ||
| state: STATE = STATE.LOADING | ||
| markdown: string = '' | ||
|
|
||
| @Prop(NamedNode) subject!: NamedNode | ||
Vinnl marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| created (): void { | ||
| loadMarkdown(this.subject.uri) | ||
| .then(responseText => { | ||
| this.markdown = responseText | ||
| this.state = STATE.RENDERING | ||
| }) | ||
| } | ||
|
|
||
| toggle (markdown: string): void { | ||
| const wasEditing = this.state === STATE.EDITING | ||
| if (wasEditing) { | ||
| this.state = STATE.LOADING | ||
| saveMarkdown(this.subject.uri, markdown) | ||
| .then(() => this.markdown = markdown) | ||
| .then(() => this.state = STATE.RENDERING) | ||
| return | ||
| } | ||
| this.state = STATE.EDITING | ||
| } | ||
|
|
||
| get isEditing (): boolean { | ||
| return this.state === STATE.EDITING | ||
| } | ||
|
|
||
| get isLoading (): boolean { | ||
| return this.state === STATE.LOADING | ||
| } | ||
|
|
||
| get isRendering (): boolean { | ||
| return this.state === STATE.RENDERING | ||
| } | ||
| } | ||
| </script> | ||
|
|
||
| <style scoped lang="scss"> | ||
| #MarkdownApp { | ||
| border: solid 3px red; | ||
| padding: 3px; | ||
| } | ||
| </style> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| <template> | ||
| <form @submit="save"> | ||
| <label> | ||
| <textarea v-model="raw"></textarea> | ||
| </label> | ||
| <button>Save</button> | ||
| </form> | ||
| </template> | ||
|
|
||
| <script lang="ts"> | ||
| import { Component, Prop, Vue } from 'vue-property-decorator'; | ||
|
|
||
| @Component | ||
| export default class MarkdownEdit extends Vue { | ||
| @Prop() markdown!: string; | ||
| raw!: string | ||
|
|
||
| created () { | ||
| this.raw = this.markdown | ||
| } | ||
|
|
||
| save (): void { | ||
| this.$emit('save', this.raw) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I presume this is throwing an event, but I haven't found yet where it is caught - can we/TypeScript trace that? (I've seen projects where it was unclear whether an event could be removed, because there was no good way to tell whether there were still listeners that were expecting it - or vice versa, that it was not clear whether a listener could be removed. Debugging was also hampered because stack traces ended at the event.)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is caught by the This is how event handling are done in Vue. I think it's fairly easy to follow the trace, as it's always direct connection between parent-child, not grandparent-child (not 100% sure on this though). |
||
| } | ||
| } | ||
| </script> | ||
|
|
||
| <!-- Add "scoped" attribute to limit CSS to this component only --> | ||
| <style scoped lang="scss"> | ||
| textarea { | ||
| height: 10em; | ||
| width: 98%; | ||
| } | ||
| </style> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| <template> | ||
| <div> | ||
| <div v-html="text"></div> | ||
| <button @click="edit">Edit</button> | ||
| </div> | ||
| </template> | ||
|
|
||
| <script lang="ts"> | ||
| import { Component, Prop, Vue } from 'vue-property-decorator'; | ||
| import marked from 'marked' | ||
|
|
||
| @Component | ||
| export default class MarkdownView extends Vue { | ||
| @Prop() markdown!: string; | ||
|
|
||
| get text (): string { | ||
| return marked(this.markdown) | ||
| } | ||
|
|
||
| edit (): void { | ||
| this.$emit('edit') | ||
| } | ||
| } | ||
| </script> | ||
|
|
||
| <!-- Add "scoped" attribute to limit CSS to this component only --> | ||
| <style scoped lang="scss"></style> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| import { NewPaneOptions, PaneDefinition } from '../types' | ||
| import solidUi from 'solid-ui' | ||
| import { NamedNode, sym } from 'rdflib' | ||
| import { saveMarkdown } from './markdown.service' | ||
|
|
||
| import Vue from 'vue' | ||
| import App from './App.vue' | ||
|
|
||
| const { icons } = solidUi | ||
|
|
||
| export const Pane: PaneDefinition = { | ||
| icon: `${icons.iconBase}noun_79217.svg`, | ||
| name: 'MarkdownPane', | ||
| label: (subject: NamedNode) => subject.uri.endsWith('.md') ? 'Handle markdown file' : null, | ||
| mintNew: function (options: NewPaneOptions) { | ||
| const newInstance = createFileName(options) | ||
| return saveMarkdown(newInstance.uri, '# This is your markdown file\n\nHere be stuff!') | ||
| .then((): NewPaneOptions => ({ | ||
| newInstance, | ||
| ...options | ||
| })) | ||
| .catch((err: any) => { | ||
| console.error('Error creating new instance of markdown file', err) | ||
| return options | ||
| }) | ||
| }, | ||
| render: (subject: NamedNode) => { | ||
| return new Vue({ | ||
| el: '#MarkdownApp', | ||
| render: h => h(App, { | ||
| props: { | ||
| subject | ||
| } | ||
| }) | ||
| }).$el | ||
| } | ||
| } | ||
|
|
||
| function createFileName (options: NewPaneOptions): NamedNode { | ||
| let uri = options.newBase | ||
| if (uri.endsWith('/')) { | ||
| uri = uri.slice(0, -1) + '.md' | ||
| } | ||
| return sym(uri) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| import solidUi from 'solid-ui' | ||
|
|
||
| const { store } = solidUi | ||
|
|
||
| export function loadMarkdown (uri: string): Promise<string> { | ||
| return store.fetcher.webOperation('GET', uri) | ||
| .then((response: any) => response.responseText) | ||
| } | ||
|
|
||
| export function saveMarkdown (uri: string, data: string): Promise<any> { | ||
| return store.fetcher.webOperation('PUT', uri, { | ||
| data, | ||
| contentType: 'text/markdown; charset=UTF-8' | ||
| }) | ||
| } | ||
|
|
||
| export enum STATE { | ||
| 'LOADING', | ||
| 'RENDERING', | ||
| 'EDITING' | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.