feat: TextStats + better searchbar

Signed-off-by: Corentin Thomasset <corentin.thomasset74@gmail.com>
This commit is contained in:
Corentin Thomasset 2020-06-01 18:27:49 +02:00
parent abc7fc6259
commit e5969a534f
6 changed files with 177 additions and 54 deletions

View file

@ -9,7 +9,7 @@
<div v-for="section in items" :key="section.title">
<v-subheader class="mt-4 pl-4">{{section.title}}</v-subheader>
<v-list-item v-for="item in section.child" :key="item.text" :to="item.link">
<v-list-item v-for="item in section.child" :key="item.text" :to="item.path">
<v-list-item-action>
<v-icon>{{ item.icon }}</v-icon>
</v-list-item-action>
@ -82,6 +82,7 @@
<script>
import SearchBar from "./components/SearchBar";
import {toolsComponents} from "./router";
export default {
props: {
@ -91,29 +92,7 @@
data: () => ({
appVersion: 'v' + process.env.APPLICATION_VERSION,
drawer: null,
items: [
{
title: 'Crypto',
child: [
{icon: 'fa-key', text: 'Token generator', link: '/token-generator'},
{icon: 'fa-font', text: 'Hash text', link: '/hash'},
{icon: 'fa-lock', text: 'Cypher/uncypher text', link: '/cypher'},
],
},
{
title: 'Converter',
child: [
{icon: 'fa-calendar', text: 'Date/Time converter', link: '/date-converter'},
],
},
{
title: 'Web',
child: [
{icon: 'fa-link', text: 'URL encode/decode', link: '/url-encoder'},
{icon: 'fa-file-image-o', text: 'File to Base64', link: '/file-to-base64'},
],
}
],
items: toolsComponents
}),
created() {
this.$vuetify.theme.dark = true

View file

@ -6,10 +6,13 @@
color="white"
hide-details
:items="items"
item-text="component.name"
item-text="text"
item-value="path"
solo-inverted
@change="choose"
:filter="filter"
clearable
cache-items
>
<template v-slot:no-data>
<v-list-item>
@ -22,23 +25,36 @@
</template>
<script>
import {toolsComponentsFlat} from '../router'
import {toolsRoutes} from '../router'
console.log(toolsComponentsFlat);
export default {
name: "SearchBar",
data() {
const vm = this;
return {
items:toolsRoutes,
items: toolsComponentsFlat,
choose(path) {
vm.$router.push(path)
vm.$router.push(path).catch(() => {
})
}
}
},
methods: {
filter(item, queryText, itemText) {
const query = queryText.trim().toLowerCase();
const nameContainsText = itemText.toLowerCase().includes(query);
const keywordContainsText = item.keywords ? item.keywords.some(keyword => keyword.toLowerCase().includes(query)) : false;
return nameContainsText || keywordContainsText;
}
}
}
</script>
<style scoped>
<style scoped lang="less">
::v-deep .v-list-item__mask{
color: inherit !important;
background: inherit !important;
}
</style>

View file

@ -7,38 +7,81 @@ import DateConverter from "./routes/tools/DateConverter";
import UrlEncoder from "./routes/tools/UrlEncoder";
import FileToBase64 from "./routes/tools/FileToBase64";
import TextCypher from "./routes/tools/TextCypher";
import TextStats from "./routes/tools/TextStats";
Vue.use(VueRouter)
const toolsRoutes = [
const toolsComponents = [
{
title: 'Crypto',
child: [
{
icon: 'fa-key',
text: 'Token generator',
path: '/token-generator',
component: TokenGenerator
component: TokenGenerator,
keywords: ['md5']
},
{
icon: 'fa-font',
text: 'Hash text',
path: '/hash',
component: Hash
},
{
icon: 'fa-lock',
text: 'Cypher/uncypher text',
path: '/cypher',
component: TextCypher
},
],
},
{
title: 'Converter',
child: [
{
icon: 'fa-calendar',
text: 'Date/Time converter',
path: '/date-converter',
component: DateConverter
},
],
},
{
title: 'Web',
child: [
{
icon: 'fa-link',
text: 'URL encode/decode',
path: '/url-encoder',
component: UrlEncoder
},
{
icon: 'fa-file-image-o',
text: 'File to Base64',
path: '/file-to-base64',
component: FileToBase64
},
],
},
{
path: '/cypher',
component: TextCypher
title: 'Miscellaneous',
child: [
{
icon: 'fa-file-text',
text: 'Text stats',
path: '/text-stats',
component: TextStats
},
],
}
]
];
const toolsComponentsFlat = toolsComponents.reduce((acc, section) => [...acc, ...section.child], [])
const routes = [
...toolsRoutes,
...toolsComponentsFlat,
{
path: '/',
component: Home
@ -59,5 +102,6 @@ const router = new VueRouter({
export default router;
export {
routes,
toolsRoutes
toolsComponents,
toolsComponentsFlat
};

View file

@ -2,7 +2,6 @@
<v-card>
<v-card-text>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad at cumque dolore dolores, dolorum eius error est eum eveniet hic illum ipsum labore minus odio quibusdam repudiandae sed ullam veritatis!
</v-card-text>
</v-card>
</template>

View file

@ -0,0 +1,72 @@
<template>
<v-card class="single-card">
<v-card-title>Text stats</v-card-title>
<v-card-text>
<v-textarea
outlined
v-model="inputText"
label="Input text"
/>
<table>
<tr>
<td><strong>Character count:</strong></td>
<td>{{ inputText.length }}</td>
</tr>
<tr>
<td><strong>Character count (without spaces):</strong></td>
<td>{{ inputText.split(' ').join('').length }}</td>
</tr>
<tr>
<td><strong>Word count:</strong></td>
<td>{{ inputText.length > 0 ? inputText.trim().split(/\s+/).length : 0 }}</td>
</tr>
<tr>
<td><strong>Line count:</strong></td>
<td>{{ inputText.length > 0 ? inputText.split(/\r\n|\r|\n/).length : 0 }}</td>
</tr>
<tr>
<td><strong>Byte size:</strong></td>
<td>{{ formatBytes(bytesSize) }} <span v-if="bytesSize >= 1024">({{bytesSize}} Bytes)</span></td>
</tr>
</table>
</v-card-text>
</v-card>
</template>
<script>
import {formatBytes} from "../../utils/helpers";
export default {
name: "TextStats",
data() {
return {
Blob: Blob,
formatBytes,
inputText: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.',
}
},
computed: {
bytesSize() {
return new Blob([this.inputText]).size
}
}
}
</script>
<style scoped lang="less">
table {
width: 100%;
tr {
td {
width: 50%;
padding: 5px;
&:first-child {
text-align: right;
}
}
}
}
</style>

View file

@ -12,7 +12,20 @@ const fileIsImage = (file) => {
return file.type.split('/')[0] === 'image';
}
const formatBytes = (bytes, decimals = 2) => {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}
export {
copyToClipboard,
fileIsImage
fileIsImage,
formatBytes
}