|
1 | 1 | <script setup lang="ts">
|
2 | 2 | import { createToken } from './token-generator.service';
|
3 | 3 | import { useCopy } from '@/composable/copy';
|
4 |
| -import { useQueryParam } from '@/composable/queryParams'; |
| 4 | +import { useQueryParamOrStorage } from '@/composable/queryParams'; |
5 | 5 | import { computedRefreshable } from '@/composable/computedRefreshable';
|
6 | 6 |
|
7 |
| -const length = useQueryParam({ name: 'length', defaultValue: 64 }); |
8 |
| -const withUppercase = useQueryParam({ name: 'uppercase', defaultValue: true }); |
9 |
| -const withLowercase = useQueryParam({ name: 'lowercase', defaultValue: true }); |
10 |
| -const withNumbers = useQueryParam({ name: 'numbers', defaultValue: true }); |
11 |
| -const withSymbols = useQueryParam({ name: 'symbols', defaultValue: false }); |
| 7 | +const count = useQueryParamOrStorage({ name: 'count', storageName: 'token-generator:count', defaultValue: 1 }); |
| 8 | +const length = useQueryParamOrStorage({ name: 'length', storageName: 'token-generator:length', defaultValue: 64 }); |
| 9 | +const withUppercase = useQueryParamOrStorage({ name: 'uppercase', storageName: 'token-generator:uppercase', defaultValue: true }); |
| 10 | +const withLowercase = useQueryParamOrStorage({ name: 'lowercase', storageName: 'token-generator:lowercase', defaultValue: true }); |
| 11 | +const withNumbers = useQueryParamOrStorage({ name: 'numbers', storageName: 'token-generator:numbers', defaultValue: true }); |
| 12 | +const withSymbols = useQueryParamOrStorage({ name: 'symbols', storageName: 'token-generator:symbols', defaultValue: false }); |
| 13 | +const deniedChars = useQueryParamOrStorage({ name: 'deny', storageName: 'token-generator:deny', defaultValue: '' }); |
12 | 14 | const { t } = useI18n();
|
13 | 15 |
|
14 |
| -const [token, refreshToken] = computedRefreshable(() => |
15 |
| - createToken({ |
16 |
| - length: length.value, |
17 |
| - withUppercase: withUppercase.value, |
18 |
| - withLowercase: withLowercase.value, |
19 |
| - withNumbers: withNumbers.value, |
20 |
| - withSymbols: withSymbols.value, |
21 |
| - }), |
| 16 | +const [tokens, refreshTokens] = computedRefreshable(() => |
| 17 | + Array.from({ length: count.value < 1 ? 1 : count.value }, |
| 18 | + () => createToken({ |
| 19 | + length: length.value, |
| 20 | + withUppercase: withUppercase.value, |
| 21 | + withLowercase: withLowercase.value, |
| 22 | + withNumbers: withNumbers.value, |
| 23 | + withSymbols: withSymbols.value, |
| 24 | + deniedChars: deniedChars.value, |
| 25 | + })).join('\n'), |
22 | 26 | );
|
23 | 27 |
|
24 |
| -const { copy } = useCopy({ source: token, text: t('tools.token-generator.copied') }); |
| 28 | +const { copy } = useCopy({ source: tokens, text: t('tools.token-generator.copied') }); |
25 | 29 | </script>
|
26 | 30 |
|
27 | 31 | <template>
|
28 | 32 | <div>
|
29 | 33 | <c-card>
|
30 | 34 | <n-form label-placement="left" label-width="140">
|
31 |
| - <div flex justify-center> |
32 |
| - <div> |
33 |
| - <n-form-item :label="t('tools.token-generator.uppercase')"> |
34 |
| - <n-switch v-model:value="withUppercase" /> |
35 |
| - </n-form-item> |
| 35 | + <n-space justify="center"> |
| 36 | + <n-form-item :label="t('tools.token-generator.uppercase')"> |
| 37 | + <n-switch v-model:value="withUppercase" /> |
| 38 | + </n-form-item> |
36 | 39 |
|
37 |
| - <n-form-item :label="t('tools.token-generator.lowercase')"> |
38 |
| - <n-switch v-model:value="withLowercase" /> |
39 |
| - </n-form-item> |
40 |
| - </div> |
| 40 | + <n-form-item :label="t('tools.token-generator.lowercase')"> |
| 41 | + <n-switch v-model:value="withLowercase" /> |
| 42 | + </n-form-item> |
| 43 | + <n-form-item :label="t('tools.token-generator.numbers')"> |
| 44 | + <n-switch v-model:value="withNumbers" /> |
| 45 | + </n-form-item> |
41 | 46 |
|
42 |
| - <div> |
43 |
| - <n-form-item :label="t('tools.token-generator.numbers')"> |
44 |
| - <n-switch v-model:value="withNumbers" /> |
45 |
| - </n-form-item> |
46 |
| - |
47 |
| - <n-form-item :label="t('tools.token-generator.symbols')"> |
48 |
| - <n-switch v-model:value="withSymbols" /> |
49 |
| - </n-form-item> |
50 |
| - </div> |
51 |
| - </div> |
| 47 | + <n-form-item :label="t('tools.token-generator.symbols')"> |
| 48 | + <n-switch v-model:value="withSymbols" /> |
| 49 | + </n-form-item> |
| 50 | + </n-space> |
52 | 51 | </n-form>
|
53 | 52 |
|
| 53 | + <n-form-item label="Denied Characters (ie, visually similar { oO01lI } or punctuations)" label-placement="top"> |
| 54 | + <c-input-text |
| 55 | + v-model:value="deniedChars" |
| 56 | + placeholder="Put characters to deny from token" |
| 57 | + /> |
| 58 | + </n-form-item> |
| 59 | + |
54 | 60 | <n-form-item :label="`${t('tools.token-generator.length')} (${length})`" label-placement="left">
|
55 |
| - <n-slider v-model:value="length" :step="1" :min="1" :max="512" /> |
| 61 | + <n-slider v-model:value="length" :step="1" :min="1" :max="512" mr-2 /> |
| 62 | + <n-input-number v-model:value="length" :min="1" :max="512" size="small" /> |
| 63 | + </n-form-item> |
| 64 | + |
| 65 | + <n-form-item label="Number of token to generate" label-placement="left"> |
| 66 | + <n-slider v-model:value="count" :step="1" :min="1" mr-2 /> |
| 67 | + <n-input-number v-model:value="count" :min="1" size="small" /> |
56 | 68 | </n-form-item>
|
57 | 69 |
|
58 | 70 | <c-input-text
|
59 |
| - v-model:value="token" |
| 71 | + v-model:value="tokens" |
60 | 72 | multiline
|
61 | 73 | :placeholder="t('tools.token-generator.tokenPlaceholder')"
|
62 | 74 | readonly
|
63 | 75 | rows="3"
|
64 | 76 | autosize
|
65 | 77 | class="token-display"
|
| 78 | + word-wrap |
66 | 79 | />
|
67 | 80 |
|
68 | 81 | <div mt-5 flex justify-center gap-3>
|
69 | 82 | <c-button @click="copy()">
|
70 | 83 | {{ t('tools.token-generator.button.copy') }}
|
71 | 84 | </c-button>
|
72 |
| - <c-button @click="refreshToken"> |
| 85 | + <c-button @click="refreshTokens"> |
73 | 86 | {{ t('tools.token-generator.button.refresh') }}
|
74 | 87 | </c-button>
|
75 | 88 | </div>
|
|
0 commit comments