components/Forms.vue (210 lines of code) (raw):

<template> <client-only placeholder="Loading..."> <div> <a :href="rasterUrl"> <v-img id="img1" v-if="isHitData" :src="base64" /> <v-img id="img1" v-else :src="url" /> </a> <v-divider /> <v-card-actions> <v-row align="center"> <v-col cols="12"> <div class="text-center"> <v-btn v-on:click="submit" :to="param" :color="convertedColor()" dark block> Generate Icon! </v-btn> </div> </v-col> </v-row> </v-card-actions> <v-form ref="generate_icon_url_form"> <v-row> <v-col class="d-flex" cols="6" sm="6"> <v-text-field @input="setLabel" :value="label" label="Label" /> </v-col> <v-col class="d-flex" cols="6" sm="6"> <v-text-field :rules="[required]" @input="setMessage" :value="message" label="Message" /> </v-col> <v-col class="d-flex" cols="6" sm="6"> <v-text-field :rules="[color_required]" @input="setColor" :value="color" label="Color" /> </v-col> <v-col class="d-flex" cols="6" sm="6"> <v-select :items="styles" :value="style" @input="setStyle" label="Styles" /> </v-col> <v-col class="d-flex" cols="6" sm="6"> <v-autocomplete @input="setLogo" :value="logo" :items="logos" label="Simple Icon" placeholder="Start typing to Search" return-object /> </v-col> <v-col class="d-flex" cols="6" sm="6"> <v-text-field :rules="[color_required]" @input="setLogoColor" :value="logoColor" label="Simple Icon Color" /> </v-col> <v-col class="d-flex" cols="12" sm="6"> <v-text-field :value="embedUrl" :rules="[url_required]" @input="setEmbedUrl" label="Embed URL (optional)" /> </v-col> </v-row> </v-form> </div> </client-only> </template> <script> import { mapActions, mapGetters } from 'vuex' import IconUrl from '~/components/IconUrl.js' const axios = require('axios').default const Color = require('color') const simpleIcons = require('~/assets/simple_icons.json').icons const simpleIconsOnlyName = ['none'].concat(simpleIcons.map(icon => icon.title)) const colorNames = require('~/assets/cssColorNames.json').colors const colorNamesWithStatus = ['none', 'success', 'important', 'critical', 'informational', 'inactive'].concat(colorNames) export default { /* eslint-disable no-console */ data () { return { iconUrl: new IconUrl(), success: true, // 送信が成功したかどうかのフラグ // base64: DEFAULT_BASE64, isHitData: false, styles: ['flat', 'flat-square', 'plastic', 'for-the-badge', 'social'], logos: simpleIconsOnlyName, required: value => !!value || 'Please be sure to input.', // 入力必須の制約 url_required: (value) => { if (value === '') { return true } const pattern = /[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)?/ return pattern.test(value) || 'Invalid Url' }, color_required: (value) => { const pattern = /^([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/ const reservedColors = colorNamesWithStatus let isValid = false if (reservedColors.includes(value) || pattern.test(value)) { isValid = true } return isValid || 'Invalid Color Code.' }, ogpData: {} } }, computed: { ...mapGetters('iconInfo', ['label', 'message', 'color', 'url', 'base64', 'style', 'logo', 'logoColor', 'param', 'rasterUrl', 'embedUrl']) }, created () { this.setGetParams() this.generateIconUrl() }, mounted () { if (window.location.search === '') { return } const variables = window.location.search.split('?')[1].split('&') const obj = {} variables.forEach(function (v, i) { const variable = v.split('=') obj[variable[0]] = Number(variable[1]) }) this.ogpData = { me: obj.message, la: obj.label, co: obj.color, st: obj.style, lo: obj.logo, lc: obj.logoColor } }, methods: { convertedColor () { try { const c = Color(`${this.color}`) return c.hex() } catch (e) { return `#${this.color}` } }, setGetParams () { if (this.$nuxt.$route.query.la !== undefined) { this.setLabel(this.$nuxt.$route.query.la) } if (this.$nuxt.$route.query.me !== undefined) { this.setMessage(this.$nuxt.$route.query.me) } if (this.$nuxt.$route.query.co !== undefined) { this.setColor(this.$nuxt.$route.query.co) } if (this.$nuxt.$route.query.st !== undefined) { this.setStyle(this.$nuxt.$route.query.st) } if (this.$nuxt.$route.query.lo !== undefined) { this.setLogo(this.$nuxt.$route.query.lo) } if (this.$nuxt.$route.query.lc !== undefined) { this.setLogoColor(this.$nuxt.$route.query.lc) } }, generateIconUrl () { // アイコンのURLを整形 this.iconUrl.setParam(this.label, this.message, this.color, this.style, this.logo, this.logoColor) const url = this.iconUrl.getUrl() this.setUrl(url) return url }, async getIcon () { try { const response = await axios.post('/getIcon', { 'url': this.url }) return response.data } catch (e) { throw e } }, async uploadUrl () { try { const response = await axios.post('/uploadIcon', { 'url': this.url }) return response.data } catch (e) { throw e } }, async submit () { if (this.$refs.generate_icon_url_form.validate()) { this.generateIconUrl() // アイコンURLを生成 this.setBase64(await this.getIcon()) // データベースからbase64を取得 if (this.base64 === 'No such document' || this.base64 === 'data:image/svg+xml;base64,' || this.base64 === undefined) { // データが無かった場合、データベースにbase64を登録する console.log(`Info: not index, get Icon`) this.isHitData = false this.uploadUrl() // base64を取得して登録 } else if (this.base64.includes('<!doctype')) { this.isHitData = false } else { this.isHitData = true } this.success = true } else { this.success = false } }, ...mapActions('iconInfo', ['setLabel', 'setMessage', 'setColor', 'setUrl', 'setBase64', 'setStyle', 'setLogo', 'setLogoColor', 'setEmbedUrl']) } } </script>