removed Login component
This commit is contained in:
parent
b6841591c4
commit
ca4480b122
@ -1,50 +0,0 @@
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
|
||||
let username = ref("");
|
||||
let password = ref("");
|
||||
let errorTxt = ref("");
|
||||
/**
|
||||
* Perform login.
|
||||
*/
|
||||
function login() {
|
||||
if (!username.value || !password.value) {
|
||||
errorTxt.value = "Please fill in both fields.";
|
||||
return;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div id="login-form">
|
||||
<form>
|
||||
<h3>Please log in:</h3>
|
||||
<div class="form-group">
|
||||
<label>Username</label>
|
||||
<input type="text" name="username" v-bind="username">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Password</label>
|
||||
<input type="password" name="password" v-bind="password">
|
||||
</div>
|
||||
|
||||
<div v-if="errorTxt" class="error">{{ errorTxt }}</div>
|
||||
|
||||
<div class="form-buttons">
|
||||
<button class="btn btn-primary" @click="login" type="button">Login</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
#login-form {
|
||||
padding: 2rem;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
</style>
|
@ -2,7 +2,7 @@
|
||||
import AboutItem from './AboutItem.vue'
|
||||
import DocumentationIcon from './icons/IconDocumentation.vue'
|
||||
import ToolingIcon from './icons/IconTooling.vue'
|
||||
import EcosystemIcon from './icons/IconEcosystem.vue'
|
||||
import QuestionIcon from './icons/IconQuestion.vue'
|
||||
import CommunityIcon from './icons/IconCommunity.vue'
|
||||
</script>
|
||||
|
||||
@ -30,16 +30,21 @@ import CommunityIcon from './icons/IconCommunity.vue'
|
||||
|
||||
<AboutItem>
|
||||
<template #icon>
|
||||
<EcosystemIcon />
|
||||
<CommunityIcon />
|
||||
</template>
|
||||
<template #heading>Client Framework</template>
|
||||
This demo todo app is based on <a href="https://vuejs.org">Vue 3</a>. We will (or already have)
|
||||
provide more samples based on other frameworks, e.g. React - although the basic idea stays the same.
|
||||
<template #heading>Feedback</template>
|
||||
<p><b>We are so eager to hear from you!</b></p>
|
||||
<ul>
|
||||
<li>Are you missing something?</li>
|
||||
<li>Any suggestion?</li>
|
||||
<li>Any question?</li>
|
||||
</ul>
|
||||
<p>We'd be REALLY happy to <a href="https://basebox.tech/open-a-aticket">hear from you</a>!</p>
|
||||
</AboutItem>
|
||||
|
||||
<AboutItem>
|
||||
<template #icon>
|
||||
<CommunityIcon />
|
||||
<QuestionIcon />
|
||||
</template>
|
||||
<template #heading>Support</template>
|
||||
|
||||
|
6
src/components/icons/IconQuestion.vue
Normal file
6
src/components/icons/IconQuestion.vue
Normal file
@ -0,0 +1,6 @@
|
||||
<template>
|
||||
<svg width="100%" height="100%" viewBox="0 0 320 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g transform="matrix(0.649422,0,0,0.681212,64.305,69.5171)">
|
||||
<path d="M64,160C64,124.7 105.744,95.67 141.044,95.67C176.344,95.67 224,124.7 224,160L224,163.6C224,185.4 212.9,205.7 194.6,217.4L152.4,244.5C127.2,260.7 112,288.6 112,318.5L112,320C112,337.7 126.3,352 144,352C161.7,352 176,337.7 176,320L176,318.6C176,310.4 180.2,302.8 187,298.4L229.2,271.3C265.8,247.7 288,207.2 288,163.6L288,160C288,89.3 211.781,31.042 141.081,31.042C70.381,31.042 0,89.3 0,160C0,177.7 14.3,192 32,192C49.7,192 64,177.7 64,160ZM144,480C165.943,480 184,461.943 184,440C184,418.057 165.943,400 144,400C122.057,400 104,418.057 104,440C104,461.943 122.057,480 144,480Z" style="fill-rule:nonzero;" fill="currentColor"/>
|
||||
</g>
|
||||
</svg></template>
|
159
src/util/net.js
Normal file
159
src/util/net.js
Normal file
@ -0,0 +1,159 @@
|
||||
/**
|
||||
* Network related functions.
|
||||
*
|
||||
* markus.thielen@basebox.health
|
||||
*/
|
||||
|
||||
import store from '@/store'
|
||||
import router from '@/router'
|
||||
|
||||
/**
|
||||
* GqlError - custom error thrown by the gqlQuery function.
|
||||
*
|
||||
* Since the GraphQL server might through multiple errors at once,
|
||||
* this error class uses a message array.
|
||||
*/
|
||||
class GqlError extends Error {
|
||||
|
||||
/**
|
||||
* Construct a GqlError.
|
||||
*
|
||||
* GqlError handles errors received from the GraphQL server as well as
|
||||
* JavaScript errors thrown by the fetch API etc.
|
||||
*
|
||||
* @param {*} error JSON server response or Error instance or just a string.
|
||||
*/
|
||||
constructor(error) {
|
||||
|
||||
/* create array of error message strings */
|
||||
const errorMessages = [];
|
||||
|
||||
if (error instanceof Error) {
|
||||
/* JavaScript Error instance */
|
||||
let msg = error.toString();
|
||||
if (msg.indexOf("Failed to fetch") > 0) {
|
||||
/* convert to a user-friendly message */
|
||||
msg = "Failed to connect to basebox server.";
|
||||
}
|
||||
errorMessages.push(msg);
|
||||
|
||||
} else if (error instanceof String) {
|
||||
errorMessages.push(error);
|
||||
|
||||
} else {
|
||||
/* assume this is a GraphQL server response (JSON) */
|
||||
try {
|
||||
for (const e of error.errors) {
|
||||
let s = e.message;
|
||||
/* add info from extension, if available */
|
||||
if (e.extensions) {
|
||||
if (e.code) {
|
||||
s += ` - ${e.extensions.code}`;
|
||||
}
|
||||
if (e.reason) {
|
||||
s += ` - ${e.extensions.reason}`;
|
||||
}
|
||||
}
|
||||
errorMessages.push(s);
|
||||
}
|
||||
} catch(e) {
|
||||
errorMessages.push("Failed to interpret error: " + e.toString());
|
||||
errorMessages.push(error.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/* concat errors into a single message for the parent classes */
|
||||
super(errorMessages.join(" / "));
|
||||
|
||||
this.errors = error.errors;
|
||||
|
||||
this.messages = errorMessages;
|
||||
this.name = "GqlError";
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this error is an authentication error (401).
|
||||
*/
|
||||
is401() {
|
||||
/* check if one of the server errors has a 401 extension */
|
||||
for (const error of this.errors) {
|
||||
if (error.extensions && error.extensions.code.toString() === "401") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Send GraphQL request to the configured server.
|
||||
*
|
||||
* @param {String} query the GraphQL query/mutation to send
|
||||
* @returns Promise with response JSON's data member on success,
|
||||
* Error with error message array on failure
|
||||
*/
|
||||
|
||||
export function gqlQuery(query)
|
||||
{
|
||||
/* prepare fetch options */
|
||||
const fetchOpt = {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ query: query }),
|
||||
};
|
||||
|
||||
/* if we're logged in, we add the authorization header */
|
||||
if (store.getters.isLoggedIn) {
|
||||
fetchOpt.headers["Authorization"] = store.getters.authData.token;
|
||||
}
|
||||
|
||||
console.info(fetchOpt);
|
||||
|
||||
return fetch(store.getters.gqlUrl, fetchOpt).then(
|
||||
/* fetch success */
|
||||
async response => {
|
||||
if (response.ok) {
|
||||
/* convert to JSON */
|
||||
const rspJson = await response.json();
|
||||
if (rspJson.data) {
|
||||
/* success */
|
||||
return new Promise((resolve, reject) => {
|
||||
resolve(rspJson.data);
|
||||
});
|
||||
} else {
|
||||
/* some errors... */
|
||||
return new Promise((resolve, reject) => {
|
||||
const error = new GqlError(rspJson);
|
||||
/* if this is a 401, we redirect to the login page */
|
||||
if (error.is401()) {
|
||||
router.push({
|
||||
name: "Login",
|
||||
query: {
|
||||
next: router.currentRoute.fullPath,
|
||||
}
|
||||
});
|
||||
}
|
||||
reject(new GqlError(rspJson));
|
||||
});
|
||||
}
|
||||
|
||||
} else {
|
||||
/* low level/network error */
|
||||
return new Promise((resolve, reject) => {
|
||||
reject(new GqlError(response.statusText));
|
||||
});
|
||||
}
|
||||
},
|
||||
/* fetch failure */
|
||||
reason => {
|
||||
return new Promise((resolve, reject) => {
|
||||
reject(new GqlError(reason));
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -1,13 +1,11 @@
|
||||
<script setup>
|
||||
import TheWelcome from '../components/TheAbout.vue'
|
||||
import { store } from "../store";
|
||||
import Login from "../components/Login.vue";
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<main>
|
||||
<!-- Force user to log in before he/she can see tasks. -->
|
||||
<Login v-if="!store.loggedIn"/>
|
||||
|
||||
</main>
|
||||
</template>
|
||||
|
Loading…
Reference in New Issue
Block a user