mirror of
https://github.com/CorentinTh/it-tools.git
synced 2025-04-21 15:26:15 -04:00
feat: urlencoder + file in base64
This commit is contained in:
parent
ee4eb30ca2
commit
d9f6c55a79
13 changed files with 260 additions and 21 deletions
5
package-lock.json
generated
5
package-lock.json
generated
|
@ -12104,11 +12104,6 @@
|
|||
"resolved": "https://registry.npmjs.org/vue/-/vue-2.6.11.tgz",
|
||||
"integrity": "sha512-VfPwgcGABbGAue9+sfrD4PuwFar7gPb1yl1UK1MwXoQPAw0BKSqWfoYCT/ThFrdEVWoI51dBuyCoiNU9bZDZxQ=="
|
||||
},
|
||||
"vue-async-computed": {
|
||||
"version": "3.8.2",
|
||||
"resolved": "https://registry.npmjs.org/vue-async-computed/-/vue-async-computed-3.8.2.tgz",
|
||||
"integrity": "sha512-If5roOhp/x0WWd0TWRD77YsuFoiIw3MbkcRlIB/FE3TqQCPje52eQp5CV5NN/7B0VAyPuGX5JQa+rc9AOcGAYw=="
|
||||
},
|
||||
"vue-cli-plugin-vuetify": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/vue-cli-plugin-vuetify/-/vue-cli-plugin-vuetify-2.0.5.tgz",
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
"register-service-worker": "^1.7.1",
|
||||
"roboto-fontface": "*",
|
||||
"vue": "^2.6.11",
|
||||
"vue-async-computed": "^3.8.2",
|
||||
"vue-cryptojs": "^2.1.4",
|
||||
"vue-router": "^3.1.6",
|
||||
"vuetify": "^2.2.11",
|
||||
|
|
|
@ -89,6 +89,13 @@
|
|||
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'},
|
||||
],
|
||||
}
|
||||
],
|
||||
}),
|
||||
|
@ -100,7 +107,7 @@
|
|||
|
||||
<style lang="less">
|
||||
html{
|
||||
overflow-y: hidden !important;
|
||||
overflow-y: auto !important;
|
||||
}
|
||||
.single-card {
|
||||
width: 100%;
|
||||
|
|
77
src/components/FileUploader.vue
Normal file
77
src/components/FileUploader.vue
Normal file
|
@ -0,0 +1,77 @@
|
|||
<template>
|
||||
<div
|
||||
class="drop-area pa-4 text-center"
|
||||
:class="{'drag-over':dragging }"
|
||||
@dragover.prevent
|
||||
@drop.prevent="imageDropped"
|
||||
@dragenter="dragEnter()"
|
||||
@dragend="dragEnd()"
|
||||
@dragleave="dragLeave()"
|
||||
@dragexit="dragExit()"
|
||||
>
|
||||
<p>Drag & drop a file here</p>
|
||||
<p class="or">or</p>
|
||||
<v-btn depressed>upload manually</v-btn>
|
||||
<p class="or">or</p>
|
||||
<v-text-field outlined dense label="Paste an url to the file" hide-details></v-text-field>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "FileUploader",
|
||||
props: ['value'],
|
||||
data() {
|
||||
return {
|
||||
dragging: false,
|
||||
dragEnterCounter: 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
imageDropped(e) {
|
||||
this.dragging = false;
|
||||
const droppedFiles = [...e.dataTransfer.files];
|
||||
|
||||
if (!droppedFiles || droppedFiles.length === 0) return;
|
||||
|
||||
this.$emit('input', droppedFiles[0])
|
||||
},
|
||||
dragEnter() {
|
||||
this.dragEnterCounter++;
|
||||
this.dragging = true;
|
||||
},
|
||||
dragLeave() {
|
||||
if(--this.dragEnterCounter <= 0){
|
||||
this.dragging = false;
|
||||
}
|
||||
},
|
||||
dragEnd() {
|
||||
this.dragging = false;
|
||||
},
|
||||
dragExit() {
|
||||
this.dragging = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.drop-area {
|
||||
border: 2px dashed #363636;
|
||||
border-radius: 10px;
|
||||
|
||||
& > *, .v-btn {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.or {
|
||||
opacity: 0.7;
|
||||
margin: 5px 0 !important;
|
||||
}
|
||||
|
||||
&.drag-over {
|
||||
border-color: #4CAF50;
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -5,7 +5,6 @@ import router from './router'
|
|||
import vuetify from './plugins/vuetify'
|
||||
import 'roboto-fontface/css/roboto/roboto-fontface.css'
|
||||
import 'font-awesome/css/font-awesome.css'
|
||||
import './plugins/async-computed'
|
||||
import './plugins/crypto-js'
|
||||
import './plugins/toast-snackbar'
|
||||
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
import Vue from 'vue';
|
||||
import AsyncComputed from 'vue-async-computed'
|
||||
|
||||
Vue.use(AsyncComputed)
|
|
@ -1,9 +1,11 @@
|
|||
import Vue from 'vue'
|
||||
import VueRouter from 'vue-router'
|
||||
import Home from './routes/Home.vue'
|
||||
import TokenGenerator from "./components/TokenGenerator";
|
||||
import Hash from "./components/Hash";
|
||||
import DateConverter from "./components/DateConverter";
|
||||
import TokenGenerator from "./routes/tools/TokenGenerator";
|
||||
import Hash from "./routes/tools/Hash";
|
||||
import DateConverter from "./routes/tools/DateConverter";
|
||||
import UrlEncoder from "./routes/tools/UrlEncoder";
|
||||
import FileToBase64 from "./routes/tools/FileToBase64";
|
||||
|
||||
Vue.use(VueRouter)
|
||||
|
||||
|
@ -24,6 +26,14 @@ const routes = [
|
|||
path: '/date-converter',
|
||||
component: DateConverter
|
||||
},
|
||||
{
|
||||
path: '/url-encoder',
|
||||
component: UrlEncoder
|
||||
},
|
||||
{
|
||||
path: '/file-to-base64',
|
||||
component: FileToBase64
|
||||
},
|
||||
{
|
||||
path: '/about',
|
||||
name: 'About',
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<v-row justify="center" align="center">
|
||||
<v-col xl="4" lg="6" md="12">
|
||||
<v-col cols="12" xl="4" lg="6" md="12">
|
||||
<v-card class="mb-5">
|
||||
<v-card-title>Input</v-card-title>
|
||||
<v-card-text>
|
||||
|
@ -37,7 +37,7 @@
|
|||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
<v-col xl="4" lg="6" md="12" >
|
||||
<v-col cols="12" xl="4" lg="6" md="12" >
|
||||
<v-card>
|
||||
<v-card-title>Dates formats</v-card-title>
|
||||
<v-card-text>
|
||||
|
@ -61,7 +61,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {copyToClipboard} from "../utils/helpers";
|
||||
import {copyToClipboard} from "../../utils/helpers";
|
||||
|
||||
export default {
|
||||
name: "DateConverter",
|
70
src/routes/tools/FileToBase64.vue
Normal file
70
src/routes/tools/FileToBase64.vue
Normal file
|
@ -0,0 +1,70 @@
|
|||
<template>
|
||||
<v-row justify="center" align="center">
|
||||
<v-col cols="12" lg="4" md="6" sm="12">
|
||||
<v-card>
|
||||
<v-card-title>File to Base64</v-card-title>
|
||||
<v-card-text>
|
||||
<FileUploader v-model="imageFile"/>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
<v-col cols="12" lg="4" md="6" sm="12" v-if="base64">
|
||||
<v-card>
|
||||
<v-card-title>Result</v-card-title>
|
||||
<v-card-text>
|
||||
<v-img :src="base64" class="mb-4" v-if="isImage"/>
|
||||
<v-textarea
|
||||
label="File in base 64"
|
||||
outlined
|
||||
readonly
|
||||
v-model="base64"
|
||||
hide-details
|
||||
/>
|
||||
<div class="text-center mt-4">
|
||||
<v-btn @click="copyBase64()" depressed>Copy base64</v-btn>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FileUploader from '../../components/FileUploader'
|
||||
import {copyToClipboard, fileIsImage} from "../../utils/helpers";
|
||||
|
||||
export default {
|
||||
name: "FileToBase64",
|
||||
components: {FileUploader},
|
||||
data() {
|
||||
return {
|
||||
imageFile: undefined,
|
||||
base64: '',
|
||||
isImage: false,
|
||||
copyBase64(){
|
||||
copyToClipboard(this.base64)
|
||||
this.$toast.success('Copied to clipboard.')
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
imageFile() {
|
||||
this.isImage = fileIsImage(this.imageFile);
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(this.imageFile);
|
||||
reader.onload = () => {
|
||||
this.base64 = reader.result;
|
||||
}
|
||||
reader.onerror = () => {
|
||||
this.base64 = '[An error as occurred]';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
import {copyToClipboard} from "../utils/helpers";
|
||||
import {copyToClipboard} from "../../utils/helpers";
|
||||
|
||||
export default {
|
||||
name: "Hash",
|
|
@ -29,7 +29,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {copyToClipboard} from "../utils/helpers";
|
||||
import {copyToClipboard} from "../../utils/helpers";
|
||||
|
||||
const shuffle = (str) => str.split('').sort(() => 0.5 - Math.random()).join('');
|
||||
const noop = () => {
|
81
src/routes/tools/UrlEncoder.vue
Normal file
81
src/routes/tools/UrlEncoder.vue
Normal file
|
@ -0,0 +1,81 @@
|
|||
<template>
|
||||
<v-row justify="center" align="center">
|
||||
<v-col cols="12" lg="4" md="6" sm="12">
|
||||
<v-card>
|
||||
<v-card-title>URL Encode</v-card-title>
|
||||
<v-card-text>
|
||||
<v-textarea
|
||||
outlined
|
||||
label="String to encode"
|
||||
v-model="encodeInput"
|
||||
/>
|
||||
<v-textarea
|
||||
readonly
|
||||
outlined
|
||||
label="URL encoded string"
|
||||
v-model="encodeOutput"
|
||||
/>
|
||||
|
||||
<div class="text-center">
|
||||
<v-btn @click="copyText(encodeOutput)" depressed>Copy result</v-btn>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" lg="4" md="6" sm="12">
|
||||
<v-card>
|
||||
<v-card-title>URL Decode</v-card-title>
|
||||
<v-card-text>
|
||||
<v-textarea
|
||||
outlined
|
||||
label="String to decode"
|
||||
v-model="decodeInput"
|
||||
/>
|
||||
<v-textarea
|
||||
readonly
|
||||
outlined
|
||||
label="URL decoded string"
|
||||
v-model="decodeOutput"
|
||||
/>
|
||||
|
||||
<div class="text-center">
|
||||
<v-btn @click="copyText(decodeOutput)" depressed>Copy result</v-btn>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
|
||||
|
||||
</v-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {copyToClipboard} from "../../utils/helpers";
|
||||
|
||||
export default {
|
||||
name: "UrlEncoder",
|
||||
data(){
|
||||
return {
|
||||
encodeInput: 'Hello world :)',
|
||||
decodeInput: 'Hello%20world%20%3A)',
|
||||
copyText(text){
|
||||
copyToClipboard(text)
|
||||
this.$toast.success('Copied to clipboard.')
|
||||
}
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
encodeOutput(){
|
||||
return encodeURIComponent(this.encodeInput)
|
||||
},
|
||||
decodeOutput(){
|
||||
return decodeURIComponent(this.encodeInput)
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -8,6 +8,11 @@ const copyToClipboard = (text) => {
|
|||
return result;
|
||||
}
|
||||
|
||||
export {
|
||||
copyToClipboard
|
||||
const fileIsImage = (file) => {
|
||||
return file.type.split('/')[0] === 'image';
|
||||
}
|
||||
|
||||
export {
|
||||
copyToClipboard,
|
||||
fileIsImage
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue