add modal to add new imap mailbox

This commit is contained in:
grimhilt 2023-02-27 22:34:36 +01:00
parent b0a0fe2f83
commit ea0bfd5a54
18 changed files with 673 additions and 97 deletions

View File

@ -1,5 +1,3 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M21.2756 4.69628C21.8922 4.07969 21.8922 3.08 21.2756 2.46342C20.659 1.84683 19.6593 1.84683 19.0427 2.46342L11.8917 9.61447L4.74063 2.46342C4.12404 1.84683 3.12436 1.84683 2.50777 2.46342C1.89118 3.08 1.89118 4.07969 2.50777 4.69628L9.65882 11.8473L2.20145 19.3047C1.58487 19.9213 1.58487 20.921 2.20145 21.5376C2.81804 22.1541 3.81773 22.1541 4.43431 21.5376L11.8917 14.0802L19.349 21.5375C19.9656 22.1541 20.9653 22.1541 21.5819 21.5375C22.1985 20.921 22.1985 19.9213 21.5819 19.3047L14.1245 11.8473L21.2756 4.69628Z" fill="#737D8C"/>
</svg>

Before

Width:  |  Height:  |  Size: 73 B

After

Width:  |  Height:  |  Size: 650 B

196
front/package-lock.json generated
View File

@ -8,6 +8,8 @@
"name": "mail",
"version": "0.1.0",
"dependencies": {
"@vueuse/components": "^9.13.0",
"@vueuse/core": "^9.13.0",
"axios": "^1.3.4",
"core-js": "^3.8.3",
"vue": "^3.2.13",
@ -2420,6 +2422,12 @@
"@types/node": "*"
}
},
"node_modules/@types/web-bluetooth": {
"version": "0.0.16",
"resolved": "https://repo.plus4u.net/operatorGate/repository/public-javascript/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz",
"integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==",
"license": "MIT"
},
"node_modules/@types/ws": {
"version": "8.5.4",
"resolved": "https://registry.npmmirror.com/@types/ws/-/ws-8.5.4.tgz",
@ -3131,6 +3139,131 @@
"dev": true,
"license": "MIT"
},
"node_modules/@vueuse/components": {
"version": "9.13.0",
"resolved": "https://repo.plus4u.net/operatorGate/repository/public-javascript/@vueuse/components/-/components-9.13.0.tgz",
"integrity": "sha512-UJ8PjQ4SGb2rsVIy9vhEc6aCu+3+2cc+xEfGNX8/M1NKIuL2Vo6c2Kc2fYFaRzWZkP8HWXu+IcwvnAzL44IEFA==",
"license": "MIT",
"dependencies": {
"@vueuse/core": "9.13.0",
"@vueuse/shared": "9.13.0",
"vue-demi": "*"
}
},
"node_modules/@vueuse/components/node_modules/vue-demi": {
"version": "0.13.11",
"resolved": "https://repo.plus4u.net/operatorGate/repository/public-javascript/vue-demi/-/vue-demi-0.13.11.tgz",
"integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==",
"hasInstallScript": true,
"license": "MIT",
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/@vueuse/core": {
"version": "9.13.0",
"resolved": "https://repo.plus4u.net/operatorGate/repository/public-javascript/@vueuse/core/-/core-9.13.0.tgz",
"integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==",
"license": "MIT",
"dependencies": {
"@types/web-bluetooth": "^0.0.16",
"@vueuse/metadata": "9.13.0",
"@vueuse/shared": "9.13.0",
"vue-demi": "*"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/core/node_modules/vue-demi": {
"version": "0.13.11",
"resolved": "https://repo.plus4u.net/operatorGate/repository/public-javascript/vue-demi/-/vue-demi-0.13.11.tgz",
"integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==",
"hasInstallScript": true,
"license": "MIT",
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/@vueuse/metadata": {
"version": "9.13.0",
"resolved": "https://repo.plus4u.net/operatorGate/repository/public-javascript/@vueuse/metadata/-/metadata-9.13.0.tgz",
"integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/shared": {
"version": "9.13.0",
"resolved": "https://repo.plus4u.net/operatorGate/repository/public-javascript/@vueuse/shared/-/shared-9.13.0.tgz",
"integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==",
"license": "MIT",
"dependencies": {
"vue-demi": "*"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/shared/node_modules/vue-demi": {
"version": "0.13.11",
"resolved": "https://repo.plus4u.net/operatorGate/repository/public-javascript/vue-demi/-/vue-demi-0.13.11.tgz",
"integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==",
"hasInstallScript": true,
"license": "MIT",
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/@webassemblyjs/ast": {
"version": "1.11.1",
"resolved": "https://registry.npmmirror.com/@webassemblyjs/ast/-/ast-1.11.1.tgz",
@ -13155,6 +13288,11 @@
"@types/node": "*"
}
},
"@types/web-bluetooth": {
"version": "0.0.16",
"resolved": "https://repo.plus4u.net/operatorGate/repository/public-javascript/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz",
"integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ=="
},
"@types/ws": {
"version": "8.5.4",
"resolved": "https://registry.npmmirror.com/@types/ws/-/ws-8.5.4.tgz",
@ -13682,6 +13820,64 @@
"integrity": "sha512-Iu8Tbg3f+emIIMmI2ycSI8QcEuAUgPTgHwesDU1eKMLE4YC/c/sFbGc70QgMq31ijRftV0R7vCm9co6rldCeOA==",
"dev": true
},
"@vueuse/components": {
"version": "9.13.0",
"resolved": "https://repo.plus4u.net/operatorGate/repository/public-javascript/@vueuse/components/-/components-9.13.0.tgz",
"integrity": "sha512-UJ8PjQ4SGb2rsVIy9vhEc6aCu+3+2cc+xEfGNX8/M1NKIuL2Vo6c2Kc2fYFaRzWZkP8HWXu+IcwvnAzL44IEFA==",
"requires": {
"@vueuse/core": "9.13.0",
"@vueuse/shared": "9.13.0",
"vue-demi": "*"
},
"dependencies": {
"vue-demi": {
"version": "0.13.11",
"resolved": "https://repo.plus4u.net/operatorGate/repository/public-javascript/vue-demi/-/vue-demi-0.13.11.tgz",
"integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==",
"requires": {}
}
}
},
"@vueuse/core": {
"version": "9.13.0",
"resolved": "https://repo.plus4u.net/operatorGate/repository/public-javascript/@vueuse/core/-/core-9.13.0.tgz",
"integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==",
"requires": {
"@types/web-bluetooth": "^0.0.16",
"@vueuse/metadata": "9.13.0",
"@vueuse/shared": "9.13.0",
"vue-demi": "*"
},
"dependencies": {
"vue-demi": {
"version": "0.13.11",
"resolved": "https://repo.plus4u.net/operatorGate/repository/public-javascript/vue-demi/-/vue-demi-0.13.11.tgz",
"integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==",
"requires": {}
}
}
},
"@vueuse/metadata": {
"version": "9.13.0",
"resolved": "https://repo.plus4u.net/operatorGate/repository/public-javascript/@vueuse/metadata/-/metadata-9.13.0.tgz",
"integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ=="
},
"@vueuse/shared": {
"version": "9.13.0",
"resolved": "https://repo.plus4u.net/operatorGate/repository/public-javascript/@vueuse/shared/-/shared-9.13.0.tgz",
"integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==",
"requires": {
"vue-demi": "*"
},
"dependencies": {
"vue-demi": {
"version": "0.13.11",
"resolved": "https://repo.plus4u.net/operatorGate/repository/public-javascript/vue-demi/-/vue-demi-0.13.11.tgz",
"integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==",
"requires": {}
}
}
},
"@webassemblyjs/ast": {
"version": "1.11.1",
"resolved": "https://registry.npmmirror.com/@webassemblyjs/ast/-/ast-1.11.1.tgz",

View File

@ -8,6 +8,8 @@
"lint": "vue-cli-service lint"
},
"dependencies": {
"@vueuse/components": "^9.13.0",
"@vueuse/core": "^9.13.0",
"axios": "^1.3.4",
"core-js": "^3.8.3",
"vue": "^3.2.13",

View File

@ -12,15 +12,15 @@ import { RouterView } from "vue-router";
</template>
<script>
import Sidebar from './views/sidebar/Sidebar';
import RoomView from './views/room/RoomView';
import Sidebar from './views/sidebar/Sidebar'
import RoomView from './views/room/RoomView'
export default {
name: 'App',
components: {
Sidebar,
RoomView
}
RoomView,
},
}
</script>

View File

@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M21.2756 4.69628C21.8922 4.07969 21.8922 3.08 21.2756 2.46342C20.659 1.84683 19.6593 1.84683 19.0427 2.46342L11.8917 9.61447L4.74063 2.46342C4.12404 1.84683 3.12436 1.84683 2.50777 2.46342C1.89118 3.08 1.89118 4.07969 2.50777 4.69628L9.65882 11.8473L2.20145 19.3047C1.58487 19.9213 1.58487 20.921 2.20145 21.5376C2.81804 22.1541 3.81773 22.1541 4.43431 21.5376L11.8917 14.0802L19.349 21.5375C19.9656 22.1541 20.9653 22.1541 21.5819 21.5375C22.1985 20.921 22.1985 19.9213 21.5819 19.3047L14.1245 11.8473L21.2756 4.69628Z" fill="#737D8C"/>
</svg>

After

Width:  |  Height:  |  Size: 650 B

View File

@ -0,0 +1,7 @@
import axios from 'axios'
export default(url='localhost') => {
return axios.create({
baseURL: url,
});
}

View File

@ -0,0 +1,7 @@
import API from './API'
export default {
getQuote() {
return API().get('/');
}
}

View File

@ -0,0 +1,222 @@
<script setup>
import { ref, computed, watchEffect } from 'vue'
import Modal from './Modal'
import API from '../../services/imapAPI';
const modal = ref(true);
const email = ref("");
const pwd = ref("");
const xoauth = ref("");
const xoauth2 = ref("");
const host = ref("");
const port = ref("993");
const error = ref("");
const knownHosts = {
'outlook.com': {
'host': 'outlook.office365.com',
},
'hotmail.com': {
'host': 'outlook.office365.com',
},
'live.com': {
'host': 'outlook.office365.com',
},
'zoho.com': {
'host': 'imap.zoho.eu',
},
'yahoo.com': {
'host': 'imap.mail.yahoo.com',
},
'icloud.com': {
'host': 'imap.mail.me.com',
},
}
const refHost = computed({
set: (val) => {
host.value = val
}
});
const err = computed({
set: (val) => { error.value = val }
});
function validateEmail(email) {
const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(String(email).toLowerCase());
}
function checkError() {
if (!validateEmail(email.value)) {
err.value = "The email is not valid.";
} else if (pwd.value == xoauth.value == xoauth2.value == "") {
err.value = "You need at least one authentification method.";
} else if ([pwd.value, xoauth.value, xoauth2.value].filter((val) => val != "").length > 1) {
err.value = "You need only one authentification method.";
} else if (host.value == "" || port.value == "") {
err.value = "You need to complete the port and the host.";
} else {
err.value = "";
}
}
function addMailboxRequest(event) {
console.log(event.target.disabled = true)
checkError();
API.getQuote().then((res) => {
console.log(res.status);
}).catch((err) => {
console.log(err.request.status)
});
}
watchEffect(() => {
if (error.value != "") {
checkError();
}
});
function mailChange() {
if (email.value.includes('@')) {
const domain = email.value.split('@')[1];
if (!knownHosts[domain]) {
refHost.value = ("imap."+domain);
} else {
refHost.value = (knownHosts[domain].host);
}
// todo check if manual
}
}
</script>
<template>
<div>
<button
@click="modal = true"
>
Open Modal!
</button>
<Modal
v-if="modal"
title="Add mailbox"
@close-modal="modal = false"
>
<template v-slot:body>
<div class="field">
<label>Email: </label>
<input @change="mailChange" v-model="email" type="email" required>
</div>
<fieldset>
<legend>Authentification method</legend>
<div class="field">
<label>Plain password:</label>
<input v-model="pwd" type="password">
</div>
<div class="field">
<label>Xoauth:</label>
<input v-model="xoauth" type="text">
</div>
<div class="field">
<label>Xoauth2:</label>
<input v-model="xoauth2" type="text">
</div>
</fieldset>
<div class="config">
<input v-model="host" id="host" type="text" placeholder="imap host">
<input v-model="port" id="port" type="number" placeholder="port">
</div>
<!-- tls -->
<div>
<button :disabled="error != ''" @click="addMailboxRequest">Add</button>
{{ error }}
</div>
</template>
</Modal>
</div>
</template>
<style>
/* Chrome, Safari, Edge, Opera */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* Firefox */
input[type=number] {
appearance: textfield;
}
.field {
margin-bottom: 5px;
}
.field > input {
margin-top: 2px;
width: 95%;
}
fieldset {
margin-top: 5px;
border-radius: 5px;
display: grid;
}
.config {
margin: 10px 0;
}
#host {
margin-right: 8px;
width: calc(95% - 100px);
}
#port {
width: 70px;
}
button {
padding: 5px;
padding: 7px 18px;
background-color: #09a35b;
color: white;
border-radius: 5px;
border: none;
text-decoration: none;
display: inline-block;
transition: opacity 0.5s;
}
button:hover {
opacity: 0.6;
}
input {
-webkit-box-flex: 1;
background-color: #303a46;
border: none;
border-radius: 4px;
color: #fff;
-ms-flex: 1;
flex: 1;
font-family: inherit;
font-size: 1.4rem;
font-weight: 400;
min-width: 0;
padding: 8px 9px;
}
input:focus {
outline: none;
}
</style>

View File

@ -0,0 +1,80 @@
<script setup>
import { vOnClickOutside } from '@vueuse/components'
import { defineEmits, defineProps } from 'vue'
const emit = defineEmits(['close-modal']);
const props = defineProps({ title: String });
function close() {
emit('close-modal');
}
</script>
<template>
<div class="modal-wrapper">
<div class="modal" v-on-click-outside="close">
<header class="modal-header">
<h2>{{ props.title }}</h2>
<div class="close-button" @click="close"></div>
</header>
<div class="modal-body">
<slot name="body">
This is the default body!
</slot>
</div>
</div>
</div>
</template>
<style scoped>
.modal-wrapper {
display: flex;
align-items: center;
position: fixed;
height: 100%;
width: 100%;
justify-content: center;
left: 0;
top: 0;
z-index: 4000;
background-color: #000;
opacity: .7;
}
.modal {
display: flex;
flex-direction: column;
border-radius: 5px;
color: white;
background-color: #1D1D23;
padding: 20px
}
.modal-header {
margin-bottom: 10px;
}
h2 {
display: inline-block;
font-size: 2.4rem;
margin: 0;
}
.close-button {
background-color: #9fa9ba;
cursor: pointer;
height: 18px;
mask: url(../../assets/close.svg);
mask-repeat: no-repeat;
mask-size: cover;
width: 18px;
float: right;
margin-top: 5px;
}
</style>

View File

@ -1,18 +1,18 @@
<template>
<div>
<Folders />
<Mailboxes />
<Users id="users"/>
</div>
</template>
<script>
import Folders from './folders/Folders';
import Users from './users/Users.vue';
import Mailboxes from './mailboxes/Mailboxes'
import Users from './users/Users.vue'
export default {
name: 'Sidebar',
components: {
Folders,
Mailboxes,
Users,
}
}

View File

@ -1,35 +0,0 @@
<template>
<div id="main" @click="setActiveMailbox(data.id)">
{{ data.mail }}
</div>
</template>
<script>
import { mapMutations } from 'vuex'
export default {
name: 'Folder',
components: {
},
props: {
data: {mail: String, id: Number}
},
methods: {
...mapMutations(['setActiveMailbox'])
}
}
</script>
<style scoped>
#main {
max-width: 32px;
white-space: normal;
word-wrap: break-word;
padding: 0px;
cursor: pointer;
}
div:hover {
background-color: aqua !important;
}
</style>

View File

@ -1,47 +0,0 @@
<template>
<div id="main">
<div id="userMenu">
<!-- deconnect -->
</div>
<span class="divider"></span>
<Folder :data="{'id': -1, 'mail': 'all'}"/>
<Folder v-for="(mailbox, index) in mailboxes" :key="index" :data="mailbox"/>
<span class="divider"></span>
<!-- <h5>Folders: </h5> -->
</div>
</template>
<script>
import { mapState } from 'vuex'
import Folder from './Folder.vue'
export default {
name: 'Folders',
components: {
Folder
},
computed: {
...mapState(['mailboxes'])
}
}
</script>
<style scoped>
#main {
display: flex;
flex-direction: column;
padding: 5px;
background-color: #2A2A33;
}
#userMenu {
width: 32px;
height: 32px;
background-color: yellow !important;
}
.divider {
border-top: 1px solid #bbb;
margin: 3px 0;
}
</style>

View File

@ -0,0 +1,48 @@
<template>
<div class="container" @click="setActiveMailbox(data.id)" :class="activeMailbox == data.id && 'active'">
{{ data.mail }}
</div>
</template>
<script>
import { mapMutations, mapState } from 'vuex'
export default {
name: 'Mailbox',
components: {
},
props: {
data: {mail: String, id: Number}
},
computed: {
...mapState(['activeMailbox'])
},
methods: {
...mapMutations(['setActiveMailbox'])
}
}
</script>
<style scoped>
.container {
max-width: 32px;
white-space: normal;
word-wrap: break-word;
padding: 5px;
margin: 1px 0;
cursor: pointer;
border-radius: 8px;
border: 2px solid transparent;
}
.container:hover {
background-color: aqua !important;
}
.active {
border: 2px solid white;
opacity: 0.9;
}
</style>

View File

@ -0,0 +1,54 @@
<template>
<div id="main">
<div id="userMenu">
<!-- deconnect -->
</div>
<span class="divider"></span>
<Mailbox :data="{'id': -1, 'mail': 'all'}"/>
<Mailbox v-for="(mailbox, index) in mailboxes" :key="index" :data="mailbox"/>
<span class="divider"></span>
<AddMailboxModal />
</div>
</template>
<script>
import { mapState } from 'vuex'
import Mailbox from './Mailbox'
import AddMailboxModal from '../../modals/AddMailboxModal'
export default {
name: 'Mailboxes',
components: {
Mailbox,
AddMailboxModal
},
computed: {
...mapState(['mailboxes'])
},
}
</script>
<style scoped>
#main {
display: flex;
flex-direction: column;
align-items: center;
padding: 5px;
background-color: #2A2A33;
color: white;
}
#userMenu {
width: 32px;
height: 32px;
background-color: yellow !important;
}
.divider {
border-top: 1px solid #bbb;
margin: 5px 0;
width: 90%;
}
</style>

View File

@ -5,7 +5,7 @@
</template>
<script>
import { mapGetters } from 'vuex';
import { mapGetters } from 'vuex'
import User from './User'
export default {

View File

@ -1296,6 +1296,11 @@
dependencies:
"@types/node" "*"
"@types/web-bluetooth@^0.0.16":
"integrity" "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ=="
"resolved" "https://repo.plus4u.net/operatorGate/repository/public-javascript/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz"
"version" "0.0.16"
"@types/ws@^8.5.1":
"integrity" "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg=="
"resolved" "https://registry.npmmirror.com/@types/ws/-/ws-8.5.4.tgz"
@ -1671,6 +1676,37 @@
"resolved" "https://registry.npmmirror.com/@vue/web-component-wrapper/-/web-component-wrapper-1.3.0.tgz"
"version" "1.3.0"
"@vueuse/components@^9.13.0":
"integrity" "sha512-UJ8PjQ4SGb2rsVIy9vhEc6aCu+3+2cc+xEfGNX8/M1NKIuL2Vo6c2Kc2fYFaRzWZkP8HWXu+IcwvnAzL44IEFA=="
"resolved" "https://repo.plus4u.net/operatorGate/repository/public-javascript/@vueuse/components/-/components-9.13.0.tgz"
"version" "9.13.0"
dependencies:
"@vueuse/core" "9.13.0"
"@vueuse/shared" "9.13.0"
"vue-demi" "*"
"@vueuse/core@^9.13.0", "@vueuse/core@9.13.0":
"integrity" "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw=="
"resolved" "https://repo.plus4u.net/operatorGate/repository/public-javascript/@vueuse/core/-/core-9.13.0.tgz"
"version" "9.13.0"
dependencies:
"@types/web-bluetooth" "^0.0.16"
"@vueuse/metadata" "9.13.0"
"@vueuse/shared" "9.13.0"
"vue-demi" "*"
"@vueuse/metadata@9.13.0":
"integrity" "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ=="
"resolved" "https://repo.plus4u.net/operatorGate/repository/public-javascript/@vueuse/metadata/-/metadata-9.13.0.tgz"
"version" "9.13.0"
"@vueuse/shared@9.13.0":
"integrity" "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw=="
"resolved" "https://repo.plus4u.net/operatorGate/repository/public-javascript/@vueuse/shared/-/shared-9.13.0.tgz"
"version" "9.13.0"
dependencies:
"vue-demi" "*"
"@webassemblyjs/ast@1.11.1":
"integrity" "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw=="
"resolved" "https://registry.npmmirror.com/@webassemblyjs/ast/-/ast-1.11.1.tgz"
@ -5907,6 +5943,11 @@
"resolved" "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz"
"version" "1.1.2"
"vue-demi@*":
"integrity" "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A=="
"resolved" "https://repo.plus4u.net/operatorGate/repository/public-javascript/vue-demi/-/vue-demi-0.13.11.tgz"
"version" "0.13.11"
"vue-eslint-parser@^8.0.1":
"integrity" "sha512-dzHGG3+sYwSf6zFBa0Gi9ZDshD7+ad14DGOdTLjruRVgZXe2J+DcZ9iUhyR48z5g1PqRa20yt3Njna/veLJL/g=="
"resolved" "https://registry.npmmirror.com/vue-eslint-parser/-/vue-eslint-parser-8.3.0.tgz"
@ -5954,7 +5995,7 @@
"resolved" "https://registry.npmmirror.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz"
"version" "1.9.1"
"vue@*", "vue@^2 || ^3.2.13", "vue@^3.0.2", "vue@^3.2.0", "vue@^3.2.13", "vue@3.2.47":
"vue@*", "vue@^2 || ^3.2.13", "vue@^3.0.0-0 || ^2.6.0", "vue@^3.0.2", "vue@^3.2.0", "vue@^3.2.13", "vue@3.2.47":
"integrity" "sha512-60188y/9Dc9WVrAZeUVSDxRQOZ+z+y5nO2ts9jWXSTkMvayiWxCWOWtBQoYjLeccfXkiiPZWAHcV+WTPhkqJHQ=="
"resolved" "https://registry.npmmirror.com/vue/-/vue-3.2.47.tgz"
"version" "3.2.47"