adds print view, fixes card sizes, types are now imported
This commit is contained in:
parent
59de19b63c
commit
749ab36ac1
17 changed files with 291 additions and 112 deletions
|
@ -146,6 +146,7 @@ button.action-close {
|
||||||
max-width: 25rem;
|
max-width: 25rem;
|
||||||
width: 50%;
|
width: 50%;
|
||||||
margin-right: -15%;
|
margin-right: -15%;
|
||||||
|
text-shadow: 0 0 3px black;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Prop, Vue } from 'vue-property-decorator'
|
import { Component, Prop, Vue } from 'vue-property-decorator'
|
||||||
|
import { Card } from '@/types'
|
||||||
|
|
||||||
import Editor from '@editorjs/editorjs'
|
import Editor from '@editorjs/editorjs'
|
||||||
import List from '@editorjs/list'
|
import List from '@editorjs/list'
|
||||||
|
|
|
@ -35,7 +35,8 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Prop, Vue } from 'vue-property-decorator'
|
import { Component, Prop, Vue } from 'vue-property-decorator'
|
||||||
import { cardWHtoStyle, iconPath } from '@/lib'
|
import { Deck, Card } from '@/types'
|
||||||
|
import { cardSizeToStyle, iconPath } from '@/lib'
|
||||||
import DeckCardEditor from '@/components/deck-card-editor.vue'
|
import DeckCardEditor from '@/components/deck-card-editor.vue'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -77,7 +78,7 @@ export default class DeckCard extends Vue {
|
||||||
private get containerStyle () {
|
private get containerStyle () {
|
||||||
const style = {
|
const style = {
|
||||||
'--highlight-color': this.card.color || this.deck.color,
|
'--highlight-color': this.card.color || this.deck.color,
|
||||||
...cardWHtoStyle(this.deck.cardWidth, this.deck.cardHeight),
|
...cardSizeToStyle(this.deck.cardSize),
|
||||||
transform: ''
|
transform: ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,8 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Prop, Vue } from 'vue-property-decorator'
|
import { Component, Prop, Vue } from 'vue-property-decorator'
|
||||||
import { cardWHtoStyle, iconPath, defaultDeck } from '@/lib'
|
import { Deck } from '@/types'
|
||||||
|
import { cardSizeToStyle, iconPath, defaultDeck } from '@/lib'
|
||||||
|
|
||||||
const emptyDeck: Deck = {
|
const emptyDeck: Deck = {
|
||||||
...defaultDeck(),
|
...defaultDeck(),
|
||||||
|
@ -34,7 +35,7 @@ export default class DeckCover extends Vue {
|
||||||
private get style () {
|
private get style () {
|
||||||
return {
|
return {
|
||||||
backgroundColor: this.deck.color,
|
backgroundColor: this.deck.color,
|
||||||
...cardWHtoStyle(this.deck.cardWidth, this.deck.cardHeight)
|
...cardSizeToStyle(this.deck.cardSize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,9 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Prop, Emit, Vue } from 'vue-property-decorator'
|
import { Component, Prop, Emit, Vue } from 'vue-property-decorator'
|
||||||
|
import { Deck, CardSize } from '@/types'
|
||||||
import DeckCover from '@/components/deck-cover.vue'
|
import DeckCover from '@/components/deck-cover.vue'
|
||||||
import { cardWHFromSize, cardSizeFromWH, iconPath } from '../lib'
|
import { iconPath } from '../lib'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: { DeckCover }
|
components: { DeckCover }
|
||||||
|
@ -35,15 +36,15 @@ export default class DeckForm extends Vue {
|
||||||
|
|
||||||
private icons = ['mouth-watering', 'robe', 'thorny-triskelion']
|
private icons = ['mouth-watering', 'robe', 'thorny-triskelion']
|
||||||
private sizes = [
|
private sizes = [
|
||||||
{ title: '88x62 (Poker)', value: '88x62' },
|
{ title: '88x62 (Poker)', value: CardSize.Poker },
|
||||||
{ title: '88x56 (Bridge)', value: '88x56' }
|
{ title: '88x56 (Bridge)', value: CardSize.Bridge }
|
||||||
]
|
]
|
||||||
|
|
||||||
private icon: string
|
private icon: string
|
||||||
private name: string
|
private name: string
|
||||||
private description: string
|
private description: string
|
||||||
private color: string
|
private color: string
|
||||||
private cardSize: string
|
private cardSize: CardSize
|
||||||
|
|
||||||
constructor () {
|
constructor () {
|
||||||
super()
|
super()
|
||||||
|
@ -51,24 +52,21 @@ export default class DeckForm extends Vue {
|
||||||
this.name = this.deck.name
|
this.name = this.deck.name
|
||||||
this.description = this.deck.description
|
this.description = this.deck.description
|
||||||
this.color = this.deck.color
|
this.color = this.deck.color
|
||||||
this.cardSize = cardSizeFromWH(this.deck.cardWidth, this.deck.cardHeight)
|
this.cardSize = this.deck.cardSize
|
||||||
}
|
}
|
||||||
|
|
||||||
private get iconPath () {
|
private get iconPath () {
|
||||||
return iconPath(this.icon)
|
return iconPath(this.icon)
|
||||||
}
|
}
|
||||||
|
|
||||||
private get newDeck () {
|
private get newDeck (): Deck {
|
||||||
const [cardWidth, cardHeight] = cardWHFromSize(this.cardSize)
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...this.deck,
|
...this.deck,
|
||||||
name: this.name,
|
name: this.name,
|
||||||
description: this.description,
|
description: this.description,
|
||||||
color: this.color,
|
color: this.color,
|
||||||
icon: this.icon,
|
icon: this.icon,
|
||||||
cardWidth,
|
cardSize: this.cardSize
|
||||||
cardHeight
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Prop, Emit, Vue } from 'vue-property-decorator'
|
import { Component, Prop, Emit, Vue } from 'vue-property-decorator'
|
||||||
|
import { Deck } from '@/types'
|
||||||
import DeckForm from './deck-form.vue'
|
import DeckForm from './deck-form.vue'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
|
63
src/components/flip-switch.vue
Normal file
63
src/components/flip-switch.vue
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
<template>
|
||||||
|
<div class="switch">
|
||||||
|
<input :id="id" class="checkbox" type="checkbox" :checked="value" @change="$emit('input', !value)" />
|
||||||
|
<label :for="id">
|
||||||
|
<div class="switch-label-text">{{ label }}</div>
|
||||||
|
<div class="switch-elements-wrapper">
|
||||||
|
<div class="switch-elements">
|
||||||
|
<div class="switch-element off"><slot name="off">NO</slot></div>
|
||||||
|
<div class="switch-element btn"></div>
|
||||||
|
<div class="switch-element on"><slot name="on">YES</slot></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Component, Prop, Vue } from 'vue-property-decorator'
|
||||||
|
|
||||||
|
@Component
|
||||||
|
export default class FlipSwitch extends Vue {
|
||||||
|
@Prop() public readonly id!: string
|
||||||
|
@Prop() public readonly value!: boolean
|
||||||
|
@Prop() public readonly label!: string
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.switch > input {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.switch .switch-elements-wrapper {
|
||||||
|
height: 2em;
|
||||||
|
width: 4em;
|
||||||
|
border: 4px solid black;
|
||||||
|
border-radius: 2em;
|
||||||
|
background-color: black;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.switch .switch-elements {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row nowrap;
|
||||||
|
transition: transform .2s ease-in;
|
||||||
|
}
|
||||||
|
.switch .switch-element {
|
||||||
|
height: 1.8em;
|
||||||
|
width: 1.8em;
|
||||||
|
margin: .1em;
|
||||||
|
line-height: 1.8em;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
.switch .btn {
|
||||||
|
background-color: gray;
|
||||||
|
border-radius: 5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.checkbox:checked + label .switch-elements-wrapper > .switch-elements {
|
||||||
|
transform: translate(-2em, 0);
|
||||||
|
}
|
||||||
|
input.checkbox:checked + label .switch-elements-wrapper {
|
||||||
|
box-shadow: 0 0 15px 2px green;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Emit, Vue } from 'vue-property-decorator'
|
import { Component, Emit, Vue } from 'vue-property-decorator'
|
||||||
|
import { Deck } from '@/types'
|
||||||
import DeckForm from './deck-form.vue'
|
import DeckForm from './deck-form.vue'
|
||||||
import { defaultDeck, randomId } from '../lib'
|
import { defaultDeck, randomId } from '../lib'
|
||||||
|
|
||||||
|
|
|
@ -7,24 +7,27 @@
|
||||||
<label for="print-option-page-size">
|
<label for="print-option-page-size">
|
||||||
Page Size
|
Page Size
|
||||||
<select class="print-option-select" id="print-option-page-size" v-model="pageSize">
|
<select class="print-option-select" id="print-option-page-size" v-model="pageSize">
|
||||||
<option :key="size" :value="size.value" v-for="size in pageSizes">{{ size.title }}</option>
|
<option :key="size.value" :value="size.value" v-for="size in pageSizes">{{ size.title }}</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label for="print-option-card-size">
|
<label for="print-option-card-size">
|
||||||
Card Size
|
Card Size
|
||||||
<select class="print-option-select" id="print-option-card-size" v-model="cardSize">
|
<select class="print-option-select" id="print-option-card-size" v-model="cardSize">
|
||||||
<option :key="size" :value="size.value" v-for="size in cardSizes">{{ size.title }}</option>
|
<option :key="size.value" :value="size.value" v-for="size in cardSizes">{{ size.title }}</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label for="print-option-arrangement">
|
<label for="print-option-arrangement">
|
||||||
Arrangement
|
Arrangement
|
||||||
<select class="print-option-select" id="print-option-arrangement" v-model="arrangement">
|
<select class="print-option-select" id="print-option-arrangement" v-model="arrangement">
|
||||||
<option :key="arrangement" :value="arrangement.value" v-for="arrangement in arrangements">{{ arrangement.title }}</option>
|
<option :key="arrangement.value" :value="arrangement.value" v-for="arrangement in arrangements">{{ arrangement.title }}</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
|
<FlipSwitch id="print-option-rounded-corners" label="Rounded Corners" v-model="roundedCorners">
|
||||||
|
</FlipSwitch>
|
||||||
|
|
||||||
<button type="submit">Print deck</button>
|
<button type="submit">Print deck</button>
|
||||||
<button class="cancel" @click.prevent="$emit('close')">cancel</button>
|
<button class="cancel" @click.prevent="$emit('close')">cancel</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -33,41 +36,49 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Prop, Emit, Vue } from 'vue-property-decorator'
|
import { Component, Prop, Vue } from 'vue-property-decorator'
|
||||||
import { cardSizeFromWH } from '../lib'
|
import { Deck, Arrangement, PageSize, CardSize } from '@/types'
|
||||||
|
import FlipSwitch from '@/components/flip-switch.vue'
|
||||||
|
|
||||||
@Component
|
@Component({
|
||||||
|
components: { FlipSwitch }
|
||||||
|
})
|
||||||
export default class EditDeckForm extends Vue {
|
export default class EditDeckForm extends Vue {
|
||||||
@Prop() public readonly deck!: Deck
|
@Prop() public readonly deck!: Deck
|
||||||
|
|
||||||
private pageSizes = [
|
private pageSizes = [
|
||||||
{ title: 'A4', value: 'a4' }, // 210mm × 297mm
|
{ title: 'A4', value: PageSize.A4 }, // 210mm × 297mm
|
||||||
{ title: 'US Letter', value: 'usletter' }, // 8.5in × 11in
|
{ title: 'US Letter', value: PageSize.USLetter }, // 8.5in × 11in
|
||||||
{ title: 'JIS-B4', value: 'jisb4' }, // 182mm × 257mm
|
{ title: 'JIS-B4', value: PageSize.JISB4 }, // 182mm × 257mm
|
||||||
{ title: 'A3', value: 'a3' }, // 297mm × 420mm
|
{ title: 'A3', value: PageSize.A3 }, // 297mm × 420mm
|
||||||
{ title: 'A5', value: 'a5' }, // 148mm × 210mm
|
{ title: 'A5', value: PageSize.A5 }, // 148mm × 210mm
|
||||||
{ title: 'US Legal', value: 'uslegal' }, // 8.5in × 14in
|
{ title: 'US Legal', value: PageSize.USLegal }, // 8.5in × 14in
|
||||||
{ title: 'US Ledger', value: 'usledger' }, // 11in × 17in
|
{ title: 'US Ledger', value: PageSize.USLedger }, // 11in × 17in
|
||||||
{ title: 'JIS-B5', value: 'jisb5' } // 257mm × 364mm
|
{ title: 'JIS-B5', value: PageSize.JISB5 } // 257mm × 364mm
|
||||||
]
|
]
|
||||||
|
|
||||||
private cardSizes = [
|
private cardSizes = [
|
||||||
{ title: '88x62 (Poker)', value: '88x62' },
|
{ title: '88x62 (Poker)', value: CardSize.Poker },
|
||||||
{ title: '88x56 (Bridge)', value: '88x56' }
|
{ title: '88x56 (Bridge)', value: CardSize.Bridge }
|
||||||
]
|
]
|
||||||
|
|
||||||
private arrangements = [
|
private arrangements = [
|
||||||
{ title: 'Doublesided', value: 'doublesided' },
|
{ title: 'Double Sided', value: Arrangement.DoubleSided },
|
||||||
{ title: 'Only Front Sides', value: 'frontonly' },
|
{ title: 'Only Front Sides', value: Arrangement.FrontOnly },
|
||||||
{ title: 'Side by Side', value: 'sidebyside' }
|
{ title: 'Side by Side', value: Arrangement.SideBySide }
|
||||||
]
|
]
|
||||||
|
|
||||||
private pageSize = 'a4'
|
private pageSize = PageSize.A4
|
||||||
private cardSize = '88x62'
|
private cardSize = CardSize.Poker
|
||||||
private arrangement = 'doublesided'
|
private arrangement = Arrangement.DoubleSided
|
||||||
|
private roundedCorners = true
|
||||||
|
|
||||||
private mounted () {
|
private mounted () {
|
||||||
this.cardSize = cardSizeFromWH(this.deck.cardWidth, this.deck.cardHeight)
|
this.cardSize = this.deck.cardSize
|
||||||
|
}
|
||||||
|
|
||||||
|
private printDeck () {
|
||||||
|
console.log('would print on', this.pageSize, `(${this.arrangement})`, this.deck.cards.length, 'cards of size', this.cardSize, this.roundedCorners ? 'with rounded corners' : '')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
16
src/lib.ts
16
src/lib.ts
|
@ -1,3 +1,5 @@
|
||||||
|
import { CardSize, Deck, Card } from './types'
|
||||||
|
|
||||||
export function randomId (): string {
|
export function randomId (): string {
|
||||||
const now = Date.now()
|
const now = Date.now()
|
||||||
const rnd = Math.round(10000000 + Math.random() * 10000000).toString(36)
|
const rnd = Math.round(10000000 + Math.random() * 10000000).toString(36)
|
||||||
|
@ -5,19 +7,16 @@ export function randomId (): string {
|
||||||
return `${now}.${rnd}`
|
return `${now}.${rnd}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export function cardSizeFromWH (w: number, h: number): string {
|
export function cardWHFromSize (size: CardSize): number[] {
|
||||||
return `${h}x${w}`
|
return size.split('x').map(v => parseFloat(v)).reverse()
|
||||||
}
|
|
||||||
|
|
||||||
export function cardWHFromSize (size: string): number[] {
|
|
||||||
return size.split('x').map(x => parseInt(x, 10)).reverse()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function iconPath (icon: string): string {
|
export function iconPath (icon: string): string {
|
||||||
return `/img/${icon}.svg`
|
return `/img/${icon}.svg`
|
||||||
}
|
}
|
||||||
|
|
||||||
export function cardWHtoStyle (w: number, h: number): object {
|
export function cardSizeToStyle (size: CardSize): object {
|
||||||
|
const [w, h] = cardWHFromSize(size)
|
||||||
const ratio = w / h
|
const ratio = w / h
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -32,8 +31,7 @@ export function defaultDeck (): Deck {
|
||||||
name: 'the nameless',
|
name: 'the nameless',
|
||||||
description: '',
|
description: '',
|
||||||
color: '#3C1C00',
|
color: '#3C1C00',
|
||||||
cardWidth: 62,
|
cardSize: CardSize.Poker,
|
||||||
cardHeight: 88,
|
|
||||||
cards: []
|
cards: []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,26 +4,26 @@ import Home from './views/Home.vue'
|
||||||
|
|
||||||
Vue.use(VueRouter)
|
Vue.use(VueRouter)
|
||||||
|
|
||||||
const routes = [
|
const routes = [{
|
||||||
{
|
path: '/',
|
||||||
path: '/',
|
name: 'Home',
|
||||||
name: 'Home',
|
component: Home
|
||||||
component: Home
|
}, {
|
||||||
},
|
path: '/deck/:id',
|
||||||
{
|
name: 'Deck',
|
||||||
path: '/deck/:id',
|
component: () => import(/* webpackChunkName "deck" */ './views/Deck.vue')
|
||||||
name: 'Deck',
|
}, {
|
||||||
component: () => import(/* webpackChunkName "deck" */ './views/Deck.vue')
|
path: '/print/:id',
|
||||||
},
|
name: 'Print',
|
||||||
{
|
component: () => import(/* webpackChunkName "print" */ './views/Print.vue')
|
||||||
path: '/about',
|
}, {
|
||||||
name: 'About',
|
path: '/about',
|
||||||
// route level code-splitting
|
name: 'About',
|
||||||
// this generates a separate chunk (about.[hash].js) for this route
|
// route level code-splitting
|
||||||
// which is lazy-loaded when the route is visited.
|
// this generates a separate chunk (about.[hash].js) for this route
|
||||||
component: () => import(/* webpackChunkName: "about" */ './views/About.vue')
|
// which is lazy-loaded when the route is visited.
|
||||||
}
|
component: () => import(/* webpackChunkName: "about" */ './views/About.vue')
|
||||||
]
|
}]
|
||||||
|
|
||||||
const router = new VueRouter({
|
const router = new VueRouter({
|
||||||
mode: 'history',
|
mode: 'history',
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { Deck, StoredStuff } from './types'
|
||||||
const KEY = 'rpg-cards-ng'
|
const KEY = 'rpg-cards-ng'
|
||||||
|
|
||||||
export default class StorageHandler {
|
export default class StorageHandler {
|
||||||
|
|
46
src/types.d.ts
vendored
46
src/types.d.ts
vendored
|
@ -1,46 +0,0 @@
|
||||||
interface KV<V> {
|
|
||||||
[key: string]: V;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ContentBlock {
|
|
||||||
type: string;
|
|
||||||
data: object;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface CardContent {
|
|
||||||
time: number;
|
|
||||||
blocks: ContentBlock[];
|
|
||||||
version: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Card {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
count: number;
|
|
||||||
tags: string[];
|
|
||||||
icon: string;
|
|
||||||
content: CardContent;
|
|
||||||
backIcon?: string;
|
|
||||||
color?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Deck {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
description: string;
|
|
||||||
color: string;
|
|
||||||
icon: string;
|
|
||||||
cards: Card[];
|
|
||||||
cardWidth: number;
|
|
||||||
cardHeight: number;
|
|
||||||
titleFontSize?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Settings {
|
|
||||||
color: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface StoredStuff {
|
|
||||||
decks: Deck[];
|
|
||||||
defaults: Settings;
|
|
||||||
}
|
|
66
src/types.ts
Normal file
66
src/types.ts
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
export const enum PageSize {
|
||||||
|
A4 = '210mm 297mm',
|
||||||
|
USLetter = '8.5in 11in',
|
||||||
|
JISB4 = '182mm 257mm',
|
||||||
|
A3 = '297mm 420mm',
|
||||||
|
A5 = '148mm 210mm',
|
||||||
|
USLegal = '8.5in 14in',
|
||||||
|
USLedger = '11in 17in',
|
||||||
|
JISB5 = '257mm 364mm'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const enum CardSize {
|
||||||
|
Poker = '89x64',
|
||||||
|
Bridge = '89x57'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const enum Arrangement {
|
||||||
|
DoubleSided = 'doublesided',
|
||||||
|
FrontOnly = 'frontonly',
|
||||||
|
SideBySide = 'sidebyside'
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KV<V> {
|
||||||
|
[key: string]: V;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ContentBlock {
|
||||||
|
type: string;
|
||||||
|
data: object;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CardContent {
|
||||||
|
time: number;
|
||||||
|
blocks: ContentBlock[];
|
||||||
|
version: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Card {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
count: number;
|
||||||
|
tags: string[];
|
||||||
|
icon: string;
|
||||||
|
content: CardContent;
|
||||||
|
backIcon?: string;
|
||||||
|
color?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Deck {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
color: string;
|
||||||
|
icon: string;
|
||||||
|
cards: Card[];
|
||||||
|
cardSize: CardSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Settings {
|
||||||
|
color: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StoredStuff {
|
||||||
|
decks: Deck[];
|
||||||
|
defaults: Settings;
|
||||||
|
}
|
|
@ -60,6 +60,7 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Vue } from 'vue-property-decorator'
|
import { Component, Vue } from 'vue-property-decorator'
|
||||||
|
import { Deck, Card } from '../types'
|
||||||
import DeckCover from '@/components/deck-cover.vue'
|
import DeckCover from '@/components/deck-cover.vue'
|
||||||
import DeckCard from '@/components/deck-card.vue'
|
import DeckCard from '@/components/deck-card.vue'
|
||||||
import EditDeckForm from '@/components/edit-deck-form.vue'
|
import EditDeckForm from '@/components/edit-deck-form.vue'
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Vue } from 'vue-property-decorator'
|
import { Component, Vue } from 'vue-property-decorator'
|
||||||
|
import { Deck } from '../types'
|
||||||
import DeckCover from '@/components/deck-cover.vue'
|
import DeckCover from '@/components/deck-cover.vue'
|
||||||
import NewDeckForm from '@/components/new-deck-form.vue'
|
import NewDeckForm from '@/components/new-deck-form.vue'
|
||||||
|
|
||||||
|
|
80
src/views/Print.vue
Normal file
80
src/views/Print.vue
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
<template>
|
||||||
|
<main id="print-view" name="print-view" :class="{ loading, 'not-found': notFound }" :style="pageSizeCSS">
|
||||||
|
<div class="page">
|
||||||
|
<header>Page 1</header>
|
||||||
|
<p>foo bar baz</p>
|
||||||
|
<ol>
|
||||||
|
<li :key="`c${i}`" v-for="(card, i) in deck.cards">{{ card.title }}</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
<div class="page">
|
||||||
|
<header>Page 2</header>
|
||||||
|
<p>foo bar baz</p>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Component, Vue } from 'vue-property-decorator'
|
||||||
|
import { Deck } from '../types'
|
||||||
|
import { iconPath } from '../lib'
|
||||||
|
|
||||||
|
@Component
|
||||||
|
export default class PrintDeck extends Vue {
|
||||||
|
private loading = true
|
||||||
|
private notFound = false
|
||||||
|
private deck: Deck | null = null
|
||||||
|
|
||||||
|
private size = '210mm 297mm'
|
||||||
|
private landscape = false // TODO: not yet implemented
|
||||||
|
|
||||||
|
private mounted () {
|
||||||
|
const currentDeckId = this.$route.params.id
|
||||||
|
this.deck = this.$storage.findDeck(currentDeckId)
|
||||||
|
if (this.deck === null) this.notFound = true
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
|
||||||
|
private get deckIcon () {
|
||||||
|
if (this.deck === null) return ''
|
||||||
|
return iconPath(this.deck.icon)
|
||||||
|
}
|
||||||
|
|
||||||
|
private get pageSizeCSS () {
|
||||||
|
const [w, h] = this.size.split(' ')
|
||||||
|
|
||||||
|
return {
|
||||||
|
'--width': w,
|
||||||
|
'--height': h,
|
||||||
|
'--size': this.size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@page {
|
||||||
|
margin: 0;
|
||||||
|
size: var(--size);
|
||||||
|
}
|
||||||
|
#print-view > .page {
|
||||||
|
display: block;
|
||||||
|
width: var(--width);
|
||||||
|
height: var(--height);
|
||||||
|
margin: 5mm auto;
|
||||||
|
background-color: white;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
@media print {
|
||||||
|
html,body {
|
||||||
|
background-color: gray;
|
||||||
|
}
|
||||||
|
#app > .home-link {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#print-view > .page {
|
||||||
|
margin: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Add table
Reference in a new issue