vue-todo/src/store.js

192 lines
4.8 KiB
JavaScript
Raw Permalink Normal View History

2023-02-28 16:54:56 +00:00
/**
* Store.js - global app state.
*
* Part of the basebox sample TODO app.
2023-04-04 17:41:37 +00:00
* https://basebox.io
2023-02-28 16:54:56 +00:00
*/
import { reactive } from 'vue'
2023-11-01 10:44:19 +00:00
import {gqlRequest} from "./util/net";
2023-02-28 16:54:56 +00:00
export const store = reactive({
2023-05-16 10:25:44 +00:00
/** User display name of the currently logged-in user */
userDisplayName: "stranger",
/* Unique user id of the currently logged in user */
userId: "",
2023-02-28 16:54:56 +00:00
2023-03-09 10:19:53 +00:00
/** base URL of basebox broker host */
2023-05-08 11:12:59 +00:00
baseboxHost: import.meta.env.BASEBOX_HOST || "http://127.0.0.1:8080",
2023-03-04 11:49:17 +00:00
2023-11-01 02:36:55 +00:00
/** User as returned from oidc-client */
user: null,
2023-03-09 10:19:53 +00:00
2023-03-11 11:15:55 +00:00
/** Fatal error message, if any */
2023-03-09 13:29:25 +00:00
fatalError: "",
2023-03-15 16:57:12 +00:00
/* array of todo lists currently known */
2023-03-17 09:51:05 +00:00
lists: [],
2023-03-15 16:57:12 +00:00
/* known tasks */
2023-03-17 09:51:05 +00:00
tasks: [],
2023-03-15 16:57:12 +00:00
2023-03-09 10:19:53 +00:00
});
/**
* Return true if the user is logged in.
*/
export function loggedIn() {
2023-11-01 02:36:55 +00:00
return store.user !== null;
2023-03-09 10:19:53 +00:00
}
/**
* Clear session data.
*/
export function clearSession() {
2023-11-01 02:36:55 +00:00
store.user = null;
store.userDisplayName = "stranger";
2023-03-09 10:19:53 +00:00
}
2023-03-11 11:15:55 +00:00
/**
* Show an error.
*/
export function showError(message) {
store.fatalError = message;
}
2023-03-04 11:49:17 +00:00
2023-03-11 11:15:55 +00:00
/**
* Clear error.
*/
export function clearError() {
store.fatalError = "";
}
2023-03-15 16:57:12 +00:00
2023-11-01 10:44:19 +00:00
/**
* Remove a task from the store.
*
* This does not remove it from the database/server!
*/
export function removeTask(task) {
const idx = store.tasks.findIndex(item => item.id === task.id);
if (idx !== -1) {
store.tasks.splice(idx, 1);
}
}
2023-03-15 16:57:12 +00:00
/**
* Initialize data store and database.
*
* Must be called by the OAuth login completion handler as soon as session data is available.
*
* If this is the first run, we need to create the logged on user, since he/she is so far known
* only to the OpenID Connect server (Keycloak).
*
* Additionally, we also create the default list here and save everything in the store.
*
2023-11-01 02:36:55 +00:00
* @param user - the user as returned from oidc-client.
2023-03-15 16:57:12 +00:00
*/
2023-11-01 02:36:55 +00:00
export async function storeInit(user) {
2023-03-15 16:57:12 +00:00
/* save user session in the store */
2023-11-01 02:36:55 +00:00
store.user = user;
store.userDisplayName = user.profile.nickname || "Logged In Stranger";
2023-05-16 10:25:44 +00:00
/* The unique user ID is the 'sub' field from the ID token. */
2023-11-01 02:36:55 +00:00
store.userId = user.profile.sub;
2023-03-15 16:57:12 +00:00
/* Create user and default list.
* We cannot run these requests in parallel, since the user record must exist in the database
* before we can create the default list.
*/
2023-03-17 09:51:05 +00:00
try {
console.info("NOTE: If next request fails, it is probably because the user already exists. In this case, the error is ignored.");
2023-11-01 10:44:19 +00:00
await gqlRequest(`mutation {
2023-03-15 16:57:12 +00:00
createUser(
2023-05-16 10:25:44 +00:00
username: "${store.userId}",
name: "${store.userDisplayName}"
2023-03-15 16:57:12 +00:00
) {
username
}
2023-03-17 09:51:05 +00:00
}`);
} catch(e) {
const errStr = e.toString();
if (errStr.indexOf("already exists") === -1) {
/* this is an error */
const e = `Failed to create user: ${errStr}`;
console.error(e);
showError(e);
return;
2023-03-15 16:57:12 +00:00
}
2023-03-17 09:51:05 +00:00
}
/* Load user info, lists and todos. */
2023-11-01 10:44:19 +00:00
gqlRequest(`query {
2023-05-16 10:25:44 +00:00
getUser(username: "${store.userId}") {
2023-03-17 09:51:05 +00:00
name
lists {
id
title
}
tasks {
id
title
description
completed
list {
id
}
2023-03-15 16:57:12 +00:00
}
}
2023-03-17 09:51:05 +00:00
}`).then(data => {
2023-05-08 11:12:59 +00:00
store.lists = data.getUser.lists ? data.getUser.lists : [];
store.tasks = data.getUser.tasks ? data.getUser.tasks : [];
2023-03-17 09:51:05 +00:00
/* create default list if necessary */
if (store.lists.length === 0) {
2023-07-07 11:21:31 +00:00
console.info("No lists found for current user; creating default list.");
2023-11-01 10:44:19 +00:00
gqlRequest(`mutation {
2023-03-17 09:51:05 +00:00
createList(
2023-04-04 17:41:37 +00:00
title: "Default",
2023-05-16 10:25:44 +00:00
user: { username: "${store.userId}" }
2023-03-17 09:51:05 +00:00
) {
title
2023-11-01 10:44:19 +00:00
id
2023-03-17 09:51:05 +00:00
}
2023-11-01 10:44:19 +00:00
}`).then(data => {
/* Save new default list in store */
store.lists.push(data.createList);
});
2023-03-17 09:51:05 +00:00
}
2023-03-15 16:57:12 +00:00
2023-03-17 09:51:05 +00:00
/* fix for basebox bug: task.list is returned as an array of List objects, where we expect just a single object */
for (const task of store.tasks) {
if (Array.isArray(task.list)) {
task.list = task.list[0];
}
}
}).catch(err => {
const e = `Failed to load user/data: ${err.toString()}`;
console.error(e);
showError(e);
});
}
const testData = {
lists: [
{ id: 1, title: "Default"},
{ id: 2, title: "House" },
{ id: 3, title: "Car" },
{ id: 4, title: "Work" },
],
/* known tasks */
tasks: [
{ id: 1, completed: false, title: "Go to dentist", description: "Last time is way too long ago...", list: { id: 1 } },
{ id: 2, completed: true, title: "Change engine oil", description: "Use the good one", list: { id: 3 } },
{ id: 3, completed: false, title: "Clean windows", description: "Regualar stuff", list: { id: 1 } },
{ id: 4, completed: false, title: "Oil stove hinges", description: "They are stiff and screechy", list: { id: 2 } },
{ id: 5, completed: false, title: "Do more benchmarking", description: "Find out how fast this thing really is", list: { id: 4 } },
],
2023-03-15 16:57:12 +00:00
2023-03-17 09:51:05 +00:00
};