feat: added memo base
This commit is contained in:
		
							parent
							
								
									1034296359
								
							
						
					
					
						commit
						0a4abde23d
					
				| @ -13,132 +13,121 @@ | ||||
|       <v-progress-circular | ||||
|         indeterminate | ||||
|         color="primary" | ||||
| 
 | ||||
|       /> | ||||
|     </div> | ||||
|     <div v-else> | ||||
|       <p>Drag & drop a file here</p> | ||||
|       <p class="or"> | ||||
|         or | ||||
|       </p> | ||||
|       <v-btn depressed @click="manualUploadClicked"> | ||||
|         select a file | ||||
|       </v-btn> | ||||
|       <p class="or">or</p> | ||||
|       <v-btn depressed @click="manualUploadClicked">select a file</v-btn> | ||||
|       <input ref="uploadInput" type="file" hidden @change="(e) => handleFiles(e.target.files[0])"> | ||||
| 
 | ||||
|       <div v-if="allowUrl"> | ||||
|         <p class="or"> | ||||
|           or | ||||
|         </p> | ||||
|         <p class="or">or</p> | ||||
|         <v-text-field | ||||
|           ref="urlInput" | ||||
|           @click:append="urlFilled(url)" | ||||
|           @keypress.enter="urlFilled(url)" | ||||
|           v-model="url" | ||||
|           append-icon="fa-arrow-right" | ||||
|           dense | ||||
|           label="Paste the file url" | ||||
|           outlined | ||||
|           :error-messages="urlErrors" | ||||
|           @click:append="urlFilled(url)" | ||||
|           @keypress.enter="urlFilled(url)" | ||||
|         /> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import {Component, Prop, Vue} from 'nuxt-property-decorator' | ||||
| 
 | ||||
| @Component | ||||
| export default class FileUploader extends Vue { | ||||
|   @Prop({default: true}) readonly allowUrl!: boolean | ||||
|   dragging = false | ||||
|   urlErrors = null | ||||
|   dragEnterCounter = 0 | ||||
|   url = '' | ||||
|   loading = false | ||||
| 
 | ||||
|   imageDropped(e) { | ||||
|     this.dragging = false | ||||
|     if (e.dataTransfer.items.length > 0) { | ||||
|       const item = e.dataTransfer.items[0] | ||||
|       switch (item.kind) { | ||||
|         case 'string': | ||||
|           item.getAsString(url => this.urlFilled(url)) | ||||
|           break | ||||
|         case 'file': | ||||
|           this.handleFiles(item.getAsFile()) | ||||
|           break | ||||
| <script> | ||||
| import * as axios from "axios"; | ||||
| export default { | ||||
|   name: "FileUploader", | ||||
|   props: { | ||||
|     allowUrl: { | ||||
|       type: Boolean, | ||||
|       default: true | ||||
|     } | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       dragging: false, | ||||
|       urlErrors: undefined, | ||||
|       dragEnterCounter: 0, | ||||
|       url: '', | ||||
|       loading: false | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     imageDropped(e) { | ||||
|       this.dragging = false; | ||||
|       if (e.dataTransfer.items.length > 0) { | ||||
|         const item = e.dataTransfer.items[0]; | ||||
|         switch (item.kind) { | ||||
|           case 'string': | ||||
|             item.getAsString(url => this.urlFilled(url)); | ||||
|             break; | ||||
|           case 'file': | ||||
|             this.handleFiles(item.getAsFile()); | ||||
|             break; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   dragEnter() { | ||||
|     this.dragEnterCounter++ | ||||
|     this.dragging = true | ||||
|   } | ||||
| 
 | ||||
|   dragLeave() { | ||||
|     if (--this.dragEnterCounter <= 0) { | ||||
|       this.dragging = false | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   async urlFilled(url) { | ||||
|     if (url && url.length > 0) { | ||||
|       this.loading = true | ||||
|       try { | ||||
|         const {data, headers} = await axios.get(url) | ||||
|         const name = url.split('/').pop() | ||||
|         const file = new File([data], name, {type: headers['content-type']}) | ||||
|         this.handleFiles(file) | ||||
|       } catch (ignored) { | ||||
|         this.urlErrors = 'Incorrect url' | ||||
|     }, | ||||
|     dragEnter() { | ||||
|       this.dragEnterCounter++; | ||||
|       this.dragging = true; | ||||
|     }, | ||||
|     dragLeave() { | ||||
|       if (--this.dragEnterCounter <= 0) { | ||||
|         this.dragging = false; | ||||
|       } | ||||
|       this.loading = false | ||||
|     }, | ||||
|     async urlFilled(url) { | ||||
|       if (url && url.length > 0) { | ||||
|         this.loading = true; | ||||
|         try { | ||||
|           const {data, headers} = await axios.get(url); | ||||
|           const name = url.split('/').pop(); | ||||
|           const file = new File([data], name, {type: headers['content-type']}) | ||||
|           this.handleFiles(file); | ||||
|         } catch (ignored) { | ||||
|           this.urlErrors = 'Incorrect url' | ||||
|         } | ||||
|         this.loading = false; | ||||
|       } | ||||
|     }, | ||||
|     dragEnd() { | ||||
|       this.dragging = false; | ||||
|     }, | ||||
|     dragExit() { | ||||
|       this.dragging = false; | ||||
|     }, | ||||
|     handleFiles(file) { | ||||
|       if (!file) return; | ||||
|       this.$emit('input', file) | ||||
|     }, | ||||
|     manualUploadClicked() { | ||||
|       this.$refs.uploadInput.click() | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   dragEnd() { | ||||
|     this.dragging = false | ||||
|   } | ||||
| 
 | ||||
|   dragExit() { | ||||
|     this.dragging = false | ||||
|   } | ||||
| 
 | ||||
|   handleFiles(file) { | ||||
|     if (!file) { | ||||
|       return | ||||
|     } | ||||
|     this.$emit('input', file) | ||||
|   } | ||||
| 
 | ||||
|   manualUploadClicked() { | ||||
|     this.$refs.uploadInput.click() | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| </script> | ||||
| 
 | ||||
| <style lang="less"> | ||||
| .drop-area { | ||||
|   border: 2px dashed rgba(255,255,255,0.3); | ||||
|   border: 2px dashed #363636; | ||||
|   border-radius: 10px; | ||||
|   background-color: rgba(255, 255, 255, 0.03); | ||||
| 
 | ||||
|   & > *, .v-btn { | ||||
|     margin: 0 !important; | ||||
|   } | ||||
| 
 | ||||
|   .or { | ||||
|     opacity: 0.7; | ||||
|     margin: 5px 0 !important; | ||||
|   } | ||||
| 
 | ||||
|   &.drag-over { | ||||
|     border-color: var(--v-primary-base); | ||||
|   } | ||||
| 
 | ||||
|   .v-input__icon { | ||||
|     button { | ||||
|       margin-top: 0 !important; | ||||
| @ -146,3 +135,152 @@ export default class FileUploader extends Vue { | ||||
|   } | ||||
| } | ||||
| </style> | ||||
| 
 | ||||
| <!--<template>--> | ||||
| <!--  <div--> | ||||
| <!--    class="drop-area pa-4 text-center"--> | ||||
| <!--    :class="{'drag-over':dragging, 'pb-0':!loading}"--> | ||||
| <!--    @dragover.prevent--> | ||||
| <!--    @drop.prevent="imageDropped"--> | ||||
| <!--    @dragenter="dragEnter()"--> | ||||
| <!--    @dragend="dragEnd()"--> | ||||
| <!--    @dragleave="dragLeave()"--> | ||||
| <!--    @dragexit="dragExit()"--> | ||||
| <!--  >--> | ||||
| <!--    <div v-if="loading">--> | ||||
| <!--      <v-progress-circular--> | ||||
| <!--        indeterminate--> | ||||
| <!--        color="primary"--> | ||||
| <!--      />--> | ||||
| <!--    </div>--> | ||||
| <!--    <div v-else>--> | ||||
| <!--      <p>Drag & drop a file here</p>--> | ||||
| <!--      <p class="or">--> | ||||
| <!--        or--> | ||||
| <!--      </p>--> | ||||
| <!--      <v-btn depressed @click="manualUploadClicked">--> | ||||
| <!--        select a file--> | ||||
| <!--      </v-btn>--> | ||||
| <!--      <input ref="uploadInput" type="file" hidden @change="(e) => handleFiles(e.target.files[0])">--> | ||||
| 
 | ||||
| <!--      <div v-if="allowUrl">--> | ||||
| <!--        <p class="or">--> | ||||
| <!--          or--> | ||||
| <!--        </p>--> | ||||
| <!--        <v-text-field--> | ||||
| <!--          ref="urlInput"--> | ||||
| <!--          v-model="url"--> | ||||
| <!--          append-icon="fa-arrow-right"--> | ||||
| <!--          dense--> | ||||
| <!--          label="Paste the file url"--> | ||||
| <!--          outlined--> | ||||
| <!--          :error-messages="urlErrors"--> | ||||
| <!--          @click:append="urlFilled(url)"--> | ||||
| <!--          @keypress.enter="urlFilled(url)"--> | ||||
| <!--        />--> | ||||
| <!--      </div>--> | ||||
| <!--    </div>--> | ||||
| <!--  </div>--> | ||||
| <!--</template>--> | ||||
| 
 | ||||
| <!--<script lang="ts">--> | ||||
| <!--import {Component, Prop, Vue} from 'nuxt-property-decorator'--> | ||||
| 
 | ||||
| <!--@Component--> | ||||
| <!--export default class FileUploader extends Vue {--> | ||||
| <!--  @Prop({default: true}) readonly allowUrl!: boolean--> | ||||
| <!--  dragging = false--> | ||||
| <!--  urlErrors: string|null = null--> | ||||
| <!--  dragEnterCounter = 0--> | ||||
| <!--  url = ''--> | ||||
| <!--  loading = false--> | ||||
| 
 | ||||
| <!--  imageDropped(e: DragEvent) {--> | ||||
| <!--    this.dragging = false--> | ||||
| <!--    if (e.dataTransfer.items.length > 0) {--> | ||||
| <!--      const item = e.dataTransfer.items[0]--> | ||||
| <!--      switch (item.kind) {--> | ||||
| <!--        case 'string':--> | ||||
| <!--          item.getAsString((url: string) => this.urlFilled(url))--> | ||||
| <!--          break--> | ||||
| <!--        case 'file':--> | ||||
| <!--          this.handleFiles(item.getAsFile())--> | ||||
| <!--          break--> | ||||
| <!--      }--> | ||||
| <!--    }--> | ||||
| <!--  }--> | ||||
| 
 | ||||
| <!--  dragEnter() {--> | ||||
| <!--    this.dragEnterCounter++--> | ||||
| <!--    this.dragging = true--> | ||||
| <!--  }--> | ||||
| 
 | ||||
| <!--  dragLeave() {--> | ||||
| <!--    if (--this.dragEnterCounter <= 0) {--> | ||||
| <!--      this.dragging = false--> | ||||
| <!--    }--> | ||||
| <!--  }--> | ||||
| 
 | ||||
| <!--  async urlFilled(url: string) {--> | ||||
| <!--    if (url && url.length > 0) {--> | ||||
| <!--      this.loading = true--> | ||||
| <!--      try {--> | ||||
| <!--        const {data, headers} = await this.$axios.$get(url)--> | ||||
| <!--        const name = url.split('/').pop()--> | ||||
| <!--        const file = new File([data], name, {type: headers['content-type']})--> | ||||
| <!--        this.handleFiles(file)--> | ||||
| <!--      } catch (ignored) {--> | ||||
| <!--        this.urlErrors = 'Incorrect url'--> | ||||
| <!--      }--> | ||||
| <!--      this.loading = false--> | ||||
| <!--    }--> | ||||
| <!--  }--> | ||||
| 
 | ||||
| <!--  dragEnd() {--> | ||||
| <!--    this.dragging = false--> | ||||
| <!--  }--> | ||||
| 
 | ||||
| <!--  dragExit() {--> | ||||
| <!--    this.dragging = false--> | ||||
| <!--  }--> | ||||
| 
 | ||||
| <!--  handleFiles(file: File) {--> | ||||
| <!--    if (!file) {--> | ||||
| <!--      return--> | ||||
| <!--    }--> | ||||
| <!--    this.$emit('input', file)--> | ||||
| <!--  }--> | ||||
| 
 | ||||
| <!--  manualUploadClicked() {--> | ||||
| <!--    this.$refs.uploadInput.click()--> | ||||
| <!--  }--> | ||||
| <!--}--> | ||||
| 
 | ||||
| <!--</script>--> | ||||
| 
 | ||||
| <!--<style lang="less">--> | ||||
| <!--.drop-area {--> | ||||
| <!--  border: 2px dashed rgba(255, 255, 255, 0.3);--> | ||||
| <!--  border-radius: 10px;--> | ||||
| <!--  background-color: rgba(255, 255, 255, 0.03);--> | ||||
| 
 | ||||
| <!--  & > *, .v-btn {--> | ||||
| <!--    margin: 0 !important;--> | ||||
| <!--  }--> | ||||
| 
 | ||||
| <!--  .or {--> | ||||
| <!--    opacity: 0.7;--> | ||||
| <!--    margin: 5px 0 !important;--> | ||||
| <!--  }--> | ||||
| 
 | ||||
| <!--  &.drag-over {--> | ||||
| <!--    border-color: var(--v-primary-base);--> | ||||
| <!--  }--> | ||||
| 
 | ||||
| <!--  .v-input__icon {--> | ||||
| <!--    button {--> | ||||
| <!--      margin-top: 0 !important;--> | ||||
| <!--    }--> | ||||
| <!--  }--> | ||||
| <!--}--> | ||||
| <!--</style>--> | ||||
|  | ||||
							
								
								
									
										103
									
								
								components/Memo.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								components/Memo.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,103 @@ | ||||
| <template> | ||||
|   <div class="memo"> | ||||
|     <ToolHeader :config="memoConfig" /> | ||||
| 
 | ||||
|     Warning: le style/aspect est toujours en wip, so focus on content <br><br> | ||||
| 
 | ||||
|     <v-row> | ||||
|       <v-col cols="12" sm="12" md="6" lg="4" v-for="item in items" :key="item.section" class="memo-section"> | ||||
|         <v-card class="mb-5"> | ||||
|           <v-card-title>{{ item.section }}</v-card-title> | ||||
|           <v-card-text> | ||||
|             <div v-for="tip in item.items" :key="tip.text" class="memo-item"> | ||||
|               <div class="memo-item-title"> | ||||
|                 {{ tip.text }} | ||||
|               </div> | ||||
|               <div v-if="tip.subtitle" class="memo-item-subtitle"> | ||||
|                 {{ tip.subtitle }} | ||||
|               </div> | ||||
|               <div v-if="tip.code" class="memo-item-code" @click="copy(tip.code)"> | ||||
|                 <pre>{{ tip.code }}</pre> | ||||
|                 <v-icon>mdi-content-copy</v-icon> | ||||
|               </div> | ||||
|             </div> | ||||
|           </v-card-text> | ||||
|         </v-card> | ||||
|       </v-col> | ||||
|     </v-row> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import {Component} from 'nuxt-property-decorator' | ||||
| import Tool from './Tool.vue' | ||||
| import type {ToolConfig} from '~/types/ToolConfig' | ||||
| import {CopyableMixin} from '~/mixins/copyable.mixin' | ||||
| import ToolHeader from '~/components/ToolHeader.vue' | ||||
| 
 | ||||
| type MemoItems = { section: string, items: { text: string, code?: string, subtitle?: string }[] }[]; | ||||
| 
 | ||||
| @Component({ | ||||
|   mixins: [CopyableMixin], | ||||
|   components: {ToolHeader} | ||||
| }) | ||||
| export default class Memo extends Tool { | ||||
|   private memoConfig: ToolConfig = this.config(); | ||||
|   private items: MemoItems = this.$t('memo') as unknown as MemoItems | ||||
| } | ||||
| </script> | ||||
| 
 | ||||
| <style lang="less"> | ||||
| .memo { | ||||
|   h1 { | ||||
|     font-weight: 300; | ||||
|     font-size: 50px; | ||||
|     margin: 0; | ||||
|     padding: 0; | ||||
|   } | ||||
| 
 | ||||
|   h2 { | ||||
|     font-weight: 400; | ||||
|   } | ||||
| 
 | ||||
|   .memo-item { | ||||
|     margin-bottom: 20px; | ||||
| 
 | ||||
|     .memo-item-title { | ||||
|       font-weight: bold; | ||||
|       font-size: 16px; | ||||
|       color: var(--v-primary-base); | ||||
|     } | ||||
| 
 | ||||
|     .memo-item-subtitle { | ||||
|       padding-bottom: 5px; | ||||
|     } | ||||
| 
 | ||||
|     .memo-item-code { | ||||
|       cursor: pointer; | ||||
|       background-color: rgba(0, 0, 0, 0.1); | ||||
|       border-radius: 4px; | ||||
|       padding: 8px 15px; | ||||
|       display: flex; | ||||
|       flex-direction: row; | ||||
|       align-items: center; | ||||
|       justify-content: center; | ||||
| 
 | ||||
|       pre { | ||||
|         flex: 1; | ||||
|         overflow-x: auto; | ||||
|       } | ||||
| 
 | ||||
|       .v-icon { | ||||
|         opacity: 0; | ||||
|       } | ||||
| 
 | ||||
|       &:hover { | ||||
|         .v-icon { | ||||
|           opacity: 1; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
| @ -1,8 +1,7 @@ | ||||
| <script lang="ts"> | ||||
| import {Component, Vue} from 'nuxt-property-decorator' | ||||
| import ToolWrapper from '~/components/ToolWrapper.vue' | ||||
| import {ToolConfig} from '~/types/ToolConfig' | ||||
| 
 | ||||
| import type {ToolConfig} from '~/types/ToolConfig' | ||||
| @Component({components: {ToolWrapper}}) | ||||
| export default class Tool extends Vue { | ||||
|   config(): ToolConfig { | ||||
|  | ||||
							
								
								
									
										44
									
								
								components/ToolHeader.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								components/ToolHeader.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,44 @@ | ||||
| <template> | ||||
|   <div class="tool-wrapper-info"> | ||||
|     <h1>{{ config.title }}</h1> | ||||
|     <div class="spacer" /> | ||||
|     <div class="description"> | ||||
|       {{ config.description }} | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import {Component, Prop, Vue} from 'nuxt-property-decorator' | ||||
| import type {ToolConfig} from '@/types/ToolConfig' | ||||
| 
 | ||||
| @Component | ||||
| export default class ToolWrapper extends Vue { | ||||
|   @Prop() readonly config!: ToolConfig; | ||||
| } | ||||
| </script> | ||||
| 
 | ||||
| <style scoped lang="less"> | ||||
| .tool-wrapper-info { | ||||
|   padding: 50px 0 30px; | ||||
| 
 | ||||
|   h1 { | ||||
|     font-weight: 300; | ||||
|     font-size: 50px; | ||||
|     margin: 0; | ||||
|     padding: 0; | ||||
|   } | ||||
| 
 | ||||
|   .spacer { | ||||
|     width: 200px; | ||||
|     height: 2px; | ||||
|     background: var(--v-primary-base); | ||||
|     background: linear-gradient(90deg, rgba(71, 177, 113, 1) 0%, rgba(59, 149, 111, 1) 60%, rgba(37, 99, 108, 1) 200%); | ||||
|     margin-bottom: 10px; | ||||
|   } | ||||
| 
 | ||||
|   .description { | ||||
|     color: #829097; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
| @ -2,24 +2,18 @@ | ||||
|   <div class="tool-wrapper"> | ||||
|     <v-row no-gutters justify="center" align="center"> | ||||
|       <v-col cols="12" xl="6" lg="8" md="10"> | ||||
|         <div class="tool-wrapper-info"> | ||||
|           <h1>{{ config.title }}</h1> | ||||
|           <div class="spacer"/> | ||||
|           <div class="description"> | ||||
|             {{ config.description }} | ||||
|           </div> | ||||
|         </div> | ||||
|         <ToolHeader :config="config" /> | ||||
| 
 | ||||
|         <template v-if="!noCard"> | ||||
|           <v-card flat> | ||||
|             <v-card-text class="pa-10"> | ||||
|               <slot/> | ||||
|               <slot /> | ||||
|             </v-card-text> | ||||
|           </v-card> | ||||
|         </template> | ||||
|         <template v-else> | ||||
|           <slot/> | ||||
|           <slot /> | ||||
|         </template> | ||||
| 
 | ||||
|       </v-col> | ||||
|     </v-row> | ||||
|   </div> | ||||
| @ -27,9 +21,9 @@ | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import {Component, Prop, Vue} from 'nuxt-property-decorator' | ||||
| import {ToolConfig} from '~/types/ToolConfig' | ||||
| 
 | ||||
| @Component | ||||
| import ToolHeader from './ToolHeader.vue' | ||||
| import type {ToolConfig} from '~/types/ToolConfig' | ||||
| @Component({components: {ToolHeader}}) | ||||
| export default class ToolWrapper extends Vue { | ||||
|   @Prop() readonly config!: ToolConfig; | ||||
|   @Prop({default: () => false}) readonly noCard!: boolean; | ||||
| @ -41,31 +35,8 @@ export default class ToolWrapper extends Vue { | ||||
| .tool-wrapper { | ||||
|   height: 100%; | ||||
| 
 | ||||
|   .tool-wrapper-info { | ||||
|     padding: 50px 0 30px; | ||||
|   } | ||||
| 
 | ||||
|   .category { | ||||
|     color: #546167; | ||||
|   } | ||||
| 
 | ||||
|   h1 { | ||||
|     font-weight: 300; | ||||
|     font-size: 50px; | ||||
|     margin: 0; | ||||
|     padding: 0; | ||||
|   } | ||||
| 
 | ||||
|   .spacer { | ||||
|     width: 200px; | ||||
|     height: 2px; | ||||
|     background: var(--v-primary-base); | ||||
|     background: linear-gradient(90deg, rgba(71, 177, 113, 1) 0%, rgba(59, 149, 111, 1) 60%, rgba(37, 99, 108, 1) 200%); | ||||
|     margin-bottom: 10px; | ||||
|   } | ||||
| 
 | ||||
|   .description { | ||||
|     color: #829097; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
|  | ||||
| @ -44,7 +44,8 @@ export default { | ||||
|     '@nuxtjs/axios', | ||||
|     // https://go.nuxtjs.dev/pwa
 | ||||
|     '@nuxtjs/pwa', | ||||
|     '@nuxtjs/svg' | ||||
|     '@nuxtjs/svg', | ||||
|     'nuxt-i18n' | ||||
|   ], | ||||
| 
 | ||||
|   // Axios module configuration (https://go.nuxtjs.dev/config-axios)
 | ||||
| @ -80,6 +81,11 @@ export default { | ||||
|     } | ||||
|   }, | ||||
| 
 | ||||
|   i18n: { | ||||
|     vueI18nLoader: true, | ||||
|     locales: ['en'] | ||||
|   }, | ||||
| 
 | ||||
|   // Build Configuration (https://go.nuxtjs.dev/config-build)
 | ||||
|   build: {}, | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										64
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										64
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -1159,6 +1159,29 @@ | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "@intlify/shared": { | ||||
|       "version": "9.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.0.0.tgz", | ||||
|       "integrity": "sha512-0r4v7dnY8g/Jfx2swUWy2GyfH/WvIpWvkU4OIupvxDTWiE8RhcpbOCVvqpVh/xGi0proHQ/r2Dhc0QSItUsfDQ==" | ||||
|     }, | ||||
|     "@intlify/vue-i18n-extensions": { | ||||
|       "version": "1.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/@intlify/vue-i18n-extensions/-/vue-i18n-extensions-1.0.2.tgz", | ||||
|       "integrity": "sha512-rnfA0ScyBXyp9xsSD4EAMGeOh1yv/AE7fhqdAdSOr5X8N39azz257umfRtzNT9sHXAKSSzpCVhIbMAkp5c/gjQ==", | ||||
|       "requires": { | ||||
|         "@babel/parser": "^7.9.6" | ||||
|       } | ||||
|     }, | ||||
|     "@intlify/vue-i18n-loader": { | ||||
|       "version": "1.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/@intlify/vue-i18n-loader/-/vue-i18n-loader-1.1.0.tgz", | ||||
|       "integrity": "sha512-9LXiztMtYKTE8t/hRwwGUp+ofrwU0sxLQLzFEOZ38zvn0DonUIQmZUj1cfz5p1Lu8BllxKbCrn6HnsRJ+LYA6g==", | ||||
|       "requires": { | ||||
|         "@intlify/shared": "^9.0.0", | ||||
|         "js-yaml": "^3.13.1", | ||||
|         "json5": "^2.1.1" | ||||
|       } | ||||
|     }, | ||||
|     "@istanbuljs/load-nyc-config": { | ||||
|       "version": "1.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", | ||||
| @ -8952,6 +8975,11 @@ | ||||
|         "is-extglob": "^2.1.1" | ||||
|       } | ||||
|     }, | ||||
|     "is-https": { | ||||
|       "version": "3.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/is-https/-/is-https-3.0.2.tgz", | ||||
|       "integrity": "sha512-jFgAKhbNF7J+lTMJxbq5z9bf1V9f8rXn9mP5RSY2GUEW5M0nOiVhVC9dNra96hQDjGpNzskIzusUnXwngqmhAA==" | ||||
|     }, | ||||
|     "is-negative-zero": { | ||||
|       "version": "2.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", | ||||
| @ -10458,6 +10486,11 @@ | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "js-cookie": { | ||||
|       "version": "2.2.1", | ||||
|       "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz", | ||||
|       "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==" | ||||
|     }, | ||||
|     "js-tokens": { | ||||
|       "version": "4.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", | ||||
| @ -10602,8 +10635,7 @@ | ||||
|     "klona": { | ||||
|       "version": "2.0.4", | ||||
|       "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.4.tgz", | ||||
|       "integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==", | ||||
|       "dev": true | ||||
|       "integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==" | ||||
|     }, | ||||
|     "last-call-webpack-plugin": { | ||||
|       "version": "3.0.0", | ||||
| @ -11540,6 +11572,29 @@ | ||||
|         "@nuxt/webpack": "2.15.2" | ||||
|       } | ||||
|     }, | ||||
|     "nuxt-i18n": { | ||||
|       "version": "6.21.0", | ||||
|       "resolved": "https://registry.npmjs.org/nuxt-i18n/-/nuxt-i18n-6.21.0.tgz", | ||||
|       "integrity": "sha512-L8MOuhVEbLxPOo6sjUZp6CaKBM+F3vkcGAhcS1+bva3YriJxa3KWPwrb1dvUccXFB46hYw4PnZ7pw8s776CLgg==", | ||||
|       "requires": { | ||||
|         "@babel/parser": "^7.5.5", | ||||
|         "@babel/traverse": "^7.5.5", | ||||
|         "@intlify/vue-i18n-extensions": "^1.0.1", | ||||
|         "@intlify/vue-i18n-loader": "^1.0.0", | ||||
|         "cookie": "^0.4.0", | ||||
|         "is-https": "^3.0.0", | ||||
|         "js-cookie": "^2.2.1", | ||||
|         "klona": "^2.0.4", | ||||
|         "vue-i18n": "^8.23.0" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "cookie": { | ||||
|           "version": "0.4.1", | ||||
|           "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", | ||||
|           "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "nuxt-property-decorator": { | ||||
|       "version": "2.9.1", | ||||
|       "resolved": "https://registry.npmjs.org/nuxt-property-decorator/-/nuxt-property-decorator-2.9.1.tgz", | ||||
| @ -16007,6 +16062,11 @@ | ||||
|       "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", | ||||
|       "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==" | ||||
|     }, | ||||
|     "vue-i18n": { | ||||
|       "version": "8.24.1", | ||||
|       "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.24.1.tgz", | ||||
|       "integrity": "sha512-iqM+npjvI9SGOAYkw1Od/y4O74gpvn5WOHeb3K125TmDJssvR62tDMMLIasPmKNbePZ1BMZ6d5jOBsrB/cK8Lw==" | ||||
|     }, | ||||
|     "vue-jest": { | ||||
|       "version": "3.0.7", | ||||
|       "resolved": "https://registry.npmjs.org/vue-jest/-/vue-jest-3.0.7.tgz", | ||||
|  | ||||
| @ -19,6 +19,7 @@ | ||||
|     "core-js": "^3.6.5", | ||||
|     "crypto-js": "^4.0.0", | ||||
|     "nuxt": "^2.14.12", | ||||
|     "nuxt-i18n": "^6.21.0", | ||||
|     "vuetify": "^2.4.5", | ||||
|     "vuetify-toast-snackbar": "^0.6.1" | ||||
|   }, | ||||
|  | ||||
| @ -3,12 +3,13 @@ | ||||
|     <v-col cols="12" sm="12" md="12"> | ||||
|       <h1>Yolo</h1> | ||||
| 
 | ||||
|       <v-row justify="center" > | ||||
|       <v-row justify="center"> | ||||
|         <v-col | ||||
|           v-for="(items, section) in toolRoutesSections" | ||||
|           :key="section" | ||||
|           cols="12" | ||||
|           sm="12" | ||||
|           md="6" | ||||
|           v-for="(items, section) in toolRoutesSections" :key="section" | ||||
|         > | ||||
|           <v-card> | ||||
|             <v-card-title>{{ section }}</v-card-title> | ||||
| @ -25,7 +26,7 @@ | ||||
|                     <v-icon>{{ item.config.icon }}</v-icon> | ||||
|                   </v-list-item-action> | ||||
|                   <v-list-item-content> | ||||
|                     <v-list-item-title v-text="item.config.title"/> | ||||
|                     <v-list-item-title v-text="item.config.title" /> | ||||
|                   </v-list-item-content> | ||||
|                 </v-list-item> | ||||
|               </v-list> | ||||
|  | ||||
| @ -1,6 +1,5 @@ | ||||
| <template> | ||||
|   <ToolWrapper :config="config()" noCard="true"> | ||||
| 
 | ||||
|   <ToolWrapper :config="config()" no-card="true"> | ||||
|     <FileUploader v-model="file"/> | ||||
| 
 | ||||
|     <div v-if="base64 || loading" class="mt-10"> | ||||
| @ -23,16 +22,15 @@ | ||||
|         </v-card-text> | ||||
|       </v-card> | ||||
|     </div> | ||||
| 
 | ||||
|   </ToolWrapper> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import {Component, Watch} from 'nuxt-property-decorator' | ||||
| import {CopyableMixin} from '@/mixins/copyable.mixin' | ||||
| import Tool from '@/components/Tool' | ||||
| import {ToolConfig} from '@/types/ToolConfig' | ||||
| import FileUploader from '~/components/FileUploader' | ||||
| import Tool from '@/components/Tool.vue' | ||||
| import type {ToolConfig} from '@/types/ToolConfig' | ||||
| import FileUploader from '~/components/FileUploader.vue' | ||||
| 
 | ||||
| @Component({ | ||||
|   mixins: [CopyableMixin], | ||||
| @ -43,28 +41,30 @@ export default class FileToBase64 extends Tool { | ||||
|     return { | ||||
|       title: 'File to base64', | ||||
|       description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Delectus distinctio dolor dolorum eaque eligendi, facilis impedit laboriosam odit placeat.', | ||||
|       icon: 'mdi-key-chain-variant', | ||||
|       icon: 'mdi-file-link-outline', | ||||
|       keywords: ['file', 'base64'] | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   file = null | ||||
|   file: Blob | null = null | ||||
|   loading = false | ||||
|   base64= '' | ||||
|   base64 = '' | ||||
| 
 | ||||
|   handleBase64(base64) { | ||||
|   handleBase64(base64: string) { | ||||
|     this.base64 = base64 | ||||
|     this.loading = false | ||||
|   } | ||||
| 
 | ||||
|   @Watch('file') | ||||
|   onFile() { | ||||
|     this.loading = true | ||||
|     this.base64 = '' | ||||
|     const reader = new FileReader() | ||||
|     reader.onload = () => this.handleBase64(reader.result) | ||||
|     reader.onerror = () => this.handleBase64('[An error as occurred]') | ||||
|     reader.readAsDataURL(this.file) | ||||
|     if (this.file) { | ||||
|       this.loading = true | ||||
|       this.base64 = '' | ||||
|       const reader = new FileReader() | ||||
|       reader.onload = () => this.handleBase64(reader.result as string) | ||||
|       reader.onerror = () => this.handleBase64('[An error as occurred]') | ||||
|       reader.readAsDataURL(this.file) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -46,7 +46,7 @@ | ||||
| import {Component} from 'nuxt-property-decorator' | ||||
| import {CopyableMixin} from '@/mixins/copyable.mixin' | ||||
| import Tool from '@/components/Tool.vue' | ||||
| import {ToolConfig} from '@/types/ToolConfig' | ||||
| import type {ToolConfig} from '@/types/ToolConfig' | ||||
| import CryptoJS from 'crypto-js' | ||||
| 
 | ||||
| const algos = { | ||||
|  | ||||
| @ -32,8 +32,7 @@ import {Component} from 'nuxt-property-decorator' | ||||
| import CryptoJS from 'crypto-js' | ||||
| import {CopyableMixin} from '~/mixins/copyable.mixin' | ||||
| import Tool from '~/components/Tool.vue' | ||||
| import {ToolConfig} from '~/types/ToolConfig' | ||||
| 
 | ||||
| import type {ToolConfig} from '~/types/ToolConfig' | ||||
| const algos = { | ||||
|   MD5: CryptoJS.MD5, | ||||
|   SHA1: CryptoJS.SHA1, | ||||
|  | ||||
| @ -29,7 +29,7 @@ | ||||
| <script lang="ts"> | ||||
| import {Component} from 'nuxt-property-decorator' | ||||
| import Tool from '~/components/Tool.vue' | ||||
| import {ToolConfig} from '~/types/ToolConfig' | ||||
| import type {ToolConfig} from '~/types/ToolConfig' | ||||
| import {CopyableMixin} from '~/mixins/copyable.mixin' | ||||
| import {shuffle} from '~/utils/string' | ||||
| 
 | ||||
|  | ||||
| @ -32,7 +32,7 @@ | ||||
| 
 | ||||
| import {Component, Ref, Watch} from 'nuxt-property-decorator' | ||||
| import {CopyableMixin} from '@/mixins/copyable.mixin' | ||||
| import {ToolConfig} from '@/types/ToolConfig' | ||||
| import type {ToolConfig} from '@/types/ToolConfig' | ||||
| import { VTextField } from 'vuetify/lib' | ||||
| import Tool from '~/components/Tool.vue' | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										63
									
								
								pages/tools/memos/git-memo.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								pages/tools/memos/git-memo.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,63 @@ | ||||
| <script lang="ts"> | ||||
| import {Component} from 'nuxt-property-decorator' | ||||
| import type {ToolConfig} from '@/types/ToolConfig' | ||||
| import Memo from '~/components/Memo.vue' | ||||
| 
 | ||||
| @Component | ||||
| export default class GitMemo extends Memo { | ||||
|   config(): ToolConfig { | ||||
|     return { | ||||
|       title: 'Git memo', | ||||
|       description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Delectus distinctio dolor dolorum eaque eligendi, facilis impedit laboriosam odit placeat.', | ||||
|       icon: 'mdi-git', | ||||
|       keywords: ['git', 'memo', 'cheat', 'sheet'] | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| 
 | ||||
| <i18n lang="yaml"> | ||||
| en: | ||||
|   memo: | ||||
|     - section: Titre de la section 1 | ||||
|       items: | ||||
|         - text: Tip n°1 | ||||
|         - text: Tip n°2 (avec sous titre | ||||
|           subtitle: Un super sous titre | ||||
|         - text: Tip n°3 (avec du code !) | ||||
|           code: rm -rf / --no-preserve-root | ||||
|         - text: Tip n°4 (avec du code et un sous titre !) | ||||
|           code: rm -rf / --no-preserve-root | ||||
|           subtitle: Un super sous titre, yeah | ||||
| 
 | ||||
|     - section: Titre de la section 2 | ||||
|       items: | ||||
|         - text: Tip n°1 | ||||
|         - text: Tip n°2 | ||||
|         - text: Tip n°3 (avec du code !) | ||||
|           code: rm -rf / --no-preserve-root | ||||
|         - text: Tip n°4 | ||||
| 
 | ||||
|     - section: Titre de la section 3 | ||||
|       items: | ||||
|         - text: Tip n°1 | ||||
|         - text: Tip n°2 (avec sous titre | ||||
|           subtitle: Un super sous titre | ||||
|         - text: Tip n°3 (avec du code !) | ||||
|           code: rm -rf / --no-preserve-root | ||||
|         - text: Tip n°4 (avec du code et un sous titre !) | ||||
|           code: rm -rf / --no-preserve-root | ||||
|           subtitle: Un super sous titre, yeah | ||||
| 
 | ||||
| 
 | ||||
|     - section: Titre de la section 4 | ||||
|       items: | ||||
|         - text: Tip n°1 | ||||
|         - text: Tip n°2 (avec sous titre | ||||
|           subtitle: Un super sous titre | ||||
|         - text: Tip n°3 (avec du code !) | ||||
|           code: rm -rf / --no-preserve-root | ||||
|         - text: Tip n°4 (avec du code et un sous titre !) | ||||
|           code: rm -rf / --no-preserve-root | ||||
|           subtitle: Un super sous titre, yeah | ||||
| </i18n> | ||||
| @ -29,7 +29,8 @@ | ||||
|       "@nuxtjs/toast", | ||||
|       "@nuxt/types", | ||||
|       "~/types/custom.d.ts", | ||||
|       "vuetify" | ||||
|       "vuetify", | ||||
|       "nuxt-i18n" | ||||
|     ] | ||||
|   }, | ||||
|   "exclude": [ | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user