small refactoring and start to support list editing
This commit is contained in:
parent
9856ad8ed1
commit
986560d284
6 changed files with 70 additions and 34 deletions
|
@ -1,6 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<ul>
|
<ul>
|
||||||
<li :key="param" v-for="param in params">{{ param }}</li>
|
<li v-for="(param, i) in params"
|
||||||
|
:key="`param${i}`"
|
||||||
|
v-editable:[i]="editable"
|
||||||
|
@keydown="handleKey(i, $event)">
|
||||||
|
{{ param }}
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -10,6 +15,30 @@ import { Component, Prop, Vue } from 'vue-property-decorator'
|
||||||
@Component
|
@Component
|
||||||
export default class DeckCardBulletList extends Vue {
|
export default class DeckCardBulletList extends Vue {
|
||||||
@Prop() public readonly params!: string[]
|
@Prop() public readonly params!: string[]
|
||||||
|
@Prop() public readonly editable!: boolean
|
||||||
|
|
||||||
|
private addEntry (index: number) {
|
||||||
|
const newParams = [...this.params]
|
||||||
|
newParams.splice(index + 1, 0, '')
|
||||||
|
this.$emit('replace', newParams)
|
||||||
|
}
|
||||||
|
|
||||||
|
private removeEntry (index: number) {
|
||||||
|
const newParams = [...this.params]
|
||||||
|
newParams.splice(index, 1)
|
||||||
|
this.$emit('replace', newParams)
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleKey (index: number, event: KeyboardEvent) {
|
||||||
|
const { key, shiftKey } = event
|
||||||
|
if (key === 'Enter' && shiftKey) {
|
||||||
|
event.preventDefault()
|
||||||
|
this.addEntry(index)
|
||||||
|
} else if (key === 'Backspace') {
|
||||||
|
const text = (event.target as HTMLElement).innerText
|
||||||
|
if (text.trim() === '') this.removeEntry(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -15,12 +15,13 @@
|
||||||
<button class="edit-close" @click.self.stop="$emit('close')" v-if="isSelection" />
|
<button class="edit-close" @click.self.stop="$emit('close')" v-if="isSelection" />
|
||||||
</header>
|
</header>
|
||||||
<main>
|
<main>
|
||||||
<component v-for="(entry, i) in card.contents"
|
<component v-for="(entry, i) in card.content"
|
||||||
:is="`deck-card-${entry.type}`"
|
:is="`deck-card-${entry.type}`"
|
||||||
:key="`e${i}`"
|
:key="`e${i}`"
|
||||||
:params="entry.params"
|
:params="entry.params"
|
||||||
:editable="isSelection"
|
:editable="isSelection"
|
||||||
@edit="editContent(i, $event)"
|
@edit="editContentFieldParam(i, $event)"
|
||||||
|
@replace="replaceContentField(i, $event)"
|
||||||
/>
|
/>
|
||||||
</main>
|
</main>
|
||||||
</section>
|
</section>
|
||||||
|
@ -89,18 +90,25 @@ export default class DeckCard extends Vue {
|
||||||
this.$emit('edit', payload)
|
this.$emit('edit', payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
private editContent (index: number, event: ContentEditEvent) {
|
private replaceContentField (index: number, newParams: Field['params']) {
|
||||||
const { param, value } = event
|
const newContent = [...this.card.content]
|
||||||
const field = this.card.contents[index]
|
const newField = {
|
||||||
const newContents = [...this.card.contents]
|
type: newContent[index].type,
|
||||||
|
params: newParams
|
||||||
|
}
|
||||||
|
newContent.splice(index, 1, newField)
|
||||||
|
|
||||||
field.params[param] = value
|
const payload = { field: 'content', value: newContent }
|
||||||
newContents.splice(index, 1, field)
|
|
||||||
|
|
||||||
const payload = { field: 'contents', value: newContents }
|
|
||||||
this.$emit('edit', payload)
|
this.$emit('edit', payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private editContentFieldParam (index: number, event: ContentEditEvent) {
|
||||||
|
const { param, value } = event
|
||||||
|
const params = [...this.card.content[index].params]
|
||||||
|
params[param] = value
|
||||||
|
this.replaceContentField(index, params)
|
||||||
|
}
|
||||||
|
|
||||||
private get icon () {
|
private get icon () {
|
||||||
const icon = this.card.icon || this.deck.icon
|
const icon = this.card.icon || this.deck.icon
|
||||||
return iconPath(icon)
|
return iconPath(icon)
|
||||||
|
|
|
@ -5,7 +5,6 @@ const eventHandlers: { [key: string]: () => void } = {}
|
||||||
|
|
||||||
Vue.directive('editable', (el, { value, arg }, vnode) => {
|
Vue.directive('editable', (el, { value, arg }, vnode) => {
|
||||||
const keypressHandler = (event: KeyboardEvent) => {
|
const keypressHandler = (event: KeyboardEvent) => {
|
||||||
console.log('keypress', event.code)
|
|
||||||
// allow line break via Shift + Enter
|
// allow line break via Shift + Enter
|
||||||
if (event.keyCode === 13 && !event.shiftKey) {
|
if (event.keyCode === 13 && !event.shiftKey) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|
|
@ -45,6 +45,6 @@ export function defaultCard (): Card {
|
||||||
count: 1,
|
count: 1,
|
||||||
tags: [],
|
tags: [],
|
||||||
icon: 'robe',
|
icon: 'robe',
|
||||||
contents: []
|
content: []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
34
src/shims.d.ts
vendored
34
src/shims.d.ts
vendored
|
@ -1,10 +1,17 @@
|
||||||
interface Settings {
|
interface Field {
|
||||||
color: string;
|
type: string;
|
||||||
|
params: (string | number)[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface StoredStuff {
|
interface Card {
|
||||||
decks: Deck[];
|
id: string;
|
||||||
defaults: Settings;
|
name: string;
|
||||||
|
count: number;
|
||||||
|
tags: string[];
|
||||||
|
icon: string;
|
||||||
|
content: Field[];
|
||||||
|
backIcon?: string;
|
||||||
|
color?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Deck {
|
interface Deck {
|
||||||
|
@ -19,18 +26,11 @@ interface Deck {
|
||||||
titleFontSize?: number;
|
titleFontSize?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Card {
|
interface Settings {
|
||||||
id: string;
|
color: string;
|
||||||
name: string;
|
|
||||||
count: number;
|
|
||||||
tags: string[];
|
|
||||||
icon: string;
|
|
||||||
contents: CardContent[];
|
|
||||||
backIcon?: string;
|
|
||||||
color?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CardContent {
|
interface StoredStuff {
|
||||||
type: string;
|
decks: Deck[];
|
||||||
params: (string | number)[];
|
defaults: Settings;
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ export default class DeckView extends Vue {
|
||||||
count: 1,
|
count: 1,
|
||||||
tags: ['foo', 'test'],
|
tags: ['foo', 'test'],
|
||||||
icon: 'robe',
|
icon: 'robe',
|
||||||
contents: [
|
content: [
|
||||||
{ type: 'subtitle', params: ['1st Level Enchantment'] },
|
{ type: 'subtitle', params: ['1st Level Enchantment'] },
|
||||||
{ type: 'rule', params: ['pointing-right'] },
|
{ type: 'rule', params: ['pointing-right'] },
|
||||||
{ type: 'property', params: ['Casting Time', '1 Action'] },
|
{ type: 'property', params: ['Casting Time', '1 Action'] },
|
||||||
|
@ -89,7 +89,7 @@ export default class DeckView extends Vue {
|
||||||
count: 1,
|
count: 1,
|
||||||
tags: ['fire', 'test'],
|
tags: ['fire', 'test'],
|
||||||
icon: 'robe',
|
icon: 'robe',
|
||||||
contents: [
|
content: [
|
||||||
{ type: 'subtitle', params: ['1st Level Evocation'] },
|
{ type: 'subtitle', params: ['1st Level Evocation'] },
|
||||||
{ type: 'rule', params: ['pointing-right'] },
|
{ type: 'rule', params: ['pointing-right'] },
|
||||||
{ type: 'property', params: ['Casting Time', '1 Action'] },
|
{ type: 'property', params: ['Casting Time', '1 Action'] },
|
||||||
|
@ -109,7 +109,7 @@ export default class DeckView extends Vue {
|
||||||
count: 1,
|
count: 1,
|
||||||
tags: ['wand', 'test'],
|
tags: ['wand', 'test'],
|
||||||
icon: 'robe',
|
icon: 'robe',
|
||||||
contents: [
|
content: [
|
||||||
{ type: 'subtitle', params: ['Wondrous Item'] },
|
{ type: 'subtitle', params: ['Wondrous Item'] },
|
||||||
{ type: 'rule', params: ['pointing-right'] },
|
{ type: 'rule', params: ['pointing-right'] },
|
||||||
{ type: 'property', params: ['Maximum charges', '7'] },
|
{ type: 'property', params: ['Maximum charges', '7'] },
|
||||||
|
@ -128,7 +128,7 @@ export default class DeckView extends Vue {
|
||||||
count: 1,
|
count: 1,
|
||||||
tags: ['goblin', 'test'],
|
tags: ['goblin', 'test'],
|
||||||
icon: 'robe',
|
icon: 'robe',
|
||||||
contents: [
|
content: [
|
||||||
{ type: 'subtitle', params: ['Small humanoid (goblinoid)'] },
|
{ type: 'subtitle', params: ['Small humanoid (goblinoid)'] },
|
||||||
{ type: 'rule', params: ['pointing-right'] },
|
{ type: 'rule', params: ['pointing-right'] },
|
||||||
{ type: 'property', params: ['Armor Class', '15 (leather armor)'] },
|
{ type: 'property', params: ['Armor Class', '15 (leather armor)'] },
|
||||||
|
|
Loading…
Add table
Reference in a new issue