メタデータプレビューとタグ候補選択のコンポーネント

This commit is contained in:
shibafu
2019-06-11 22:16:40 +09:00
parent a1cb313d4f
commit b8482e0e3c
6 changed files with 140 additions and 6 deletions

View File

@@ -1,9 +1,45 @@
import Vue from 'vue';
import TagInput from "./components/TagInput.vue";
import MetadataPreview from './components/MetadataPreview.vue';
export const bus = new Vue({name: "EventBus"});
new Vue({
el: '#app',
data: {
metadata: null
},
components: {
TagInput
TagInput,
MetadataPreview
},
mounted() {
// TODO: 編集モード時はすぐにメタデータを取得する
},
methods: {
// オカズリンクの変更時
onChangeLink(event: Event) {
if (event.target instanceof HTMLInputElement) {
const url = event.target.value;
if (url.trim() === '' || !/^https?:\/\//.test(url)) {
this.metadata = null;
return;
}
$.ajax({
url: '/api/checkin/card',
method: 'get',
type: 'json',
data: {
url
}
}).then(data => {
this.metadata = data;
}).catch(e => {
this.metadata = null;
});
}
}
}
});

View File

@@ -0,0 +1,66 @@
<template>
<div class="form-row" v-if="metadata !== null">
<div class="form-group col-sm-12">
<div class="card link-card-mini mb-2 px-0">
<div class="row no-gutters">
<div class="col-4 justify-content-center align-items-center">
<img :src="metadata.image" alt="Thumbnail" class="card-img-top-to-left bg-secondary">
</div>
<div class="col-8">
<div class="card-body">
<h6 class="card-title font-weight-bold" style="font-size: small;">{{ metadata.title }}</h6>
<template v-if="suggestions.length > 0">
<p class="card-text mb-2" style="font-size: small;">タグ候補<br><span class="text-secondary">(クリックするとタグ入力欄にコピーできます)</span></p>
<ul class="list-inline d-inline">
<li v-for="tag in suggestions"
class="list-inline-item badge badge-primary metadata-tag-item"
@click="addTag(tag)"><span class="oi oi-tag"></span> {{ tag }}</li>
</ul>
</template>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import {Vue, Component, Prop} from "vue-property-decorator";
import {bus} from "../checkin";
type Metadata = {
url: string,
title: string | null,
description: string | null,
image: string | null,
expires_at: string | null,
tags: {
name: string
}[],
};
@Component
export default class MetadataPreview extends Vue {
@Prop() readonly metadata!: Metadata | null;
addTag(tag: string) {
bus.$emit("add-tag", tag);
}
get suggestions() {
if (this.metadata === null) {
return [];
}
return this.metadata.tags.map(t => t.name);
}
}
</script>
<style lang="scss" scoped>
.metadata-tag-item {
cursor: pointer;
user-select: none;
}
</style>

View File

@@ -17,6 +17,7 @@
<script lang="ts">
import {Vue, Component, Prop} from "vue-property-decorator";
import {bus} from "../checkin";
@Component
export default class TagInput extends Vue {
@@ -28,6 +29,10 @@
tags: string[] = this.value.trim() !== "" ? this.value.trim().split(" ") : [];
buffer: string = "";
created() {
bus.$on("add-tag", (tag: string) => this.tags.push(tag));
}
onKeyDown(event: KeyboardEvent) {
if (this.buffer.trim() !== "") {
switch (event.key) {