-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
This is the base version of the charts, it is incomplete and still requires fine tuning #33
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// src/data/DataService.ts | ||
import PocketBase from 'pocketbase'; | ||
|
||
|
||
|
||
export class DataService { | ||
private pocketBaseInstance = new PocketBase('http://127.0.0.1:8090'); | ||
private isAuthenticated = false; | ||
|
||
|
||
async authenticate(email: string, password: string) { | ||
if (!this.isAuthenticated) { | ||
await this.pocketBaseInstance.admins.authWithPassword(email, password); | ||
this.isAuthenticated = true; | ||
|
||
} | ||
} | ||
|
||
async fetchPaginatedData(collectionName: string, page: number, batchSize: number) { | ||
return await this.pocketBaseInstance.collection(collectionName).getList(page, batchSize); | ||
} | ||
|
||
subscribeToCollection(collectionName: string, callback: (data: any) => void) { | ||
this.pocketBaseInstance.collection(collectionName).subscribe('*', (e) => callback(e.record)); | ||
console.log(`Subscribed to real-time updates for collection: ${collectionName}`); | ||
} | ||
|
||
unsubscribeFromCollection(collectionName: string) { | ||
this.pocketBaseInstance.collection(collectionName).unsubscribe('*'); | ||
console.log(`Unsubscribed from real-time updates for collection: ${collectionName}`); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// StoreService.ts | ||
import PocketBase from 'pocketbase'; | ||
|
||
const pb = new PocketBase('http://127.0.0.1:8090'); | ||
let isAuthenticated = false; | ||
pb.autoCancellation(false); | ||
|
||
// Define the RecordData type explicitly for PocketBase records | ||
export type RecordData = { [key: string]: any }; | ||
|
||
// Function to authenticate PocketBase before any data fetch or subscription | ||
async function authenticate() { | ||
if (!isAuthenticated) { | ||
const email = import.meta.env.VITE_EMAIL; | ||
const password = import.meta.env.VITE_PASSWORD; | ||
|
||
try { | ||
await pb.admins.authWithPassword(email, password); | ||
isAuthenticated = true; | ||
console.log('Authenticated successfully'); | ||
} catch (error) { | ||
console.error('Authentication failed:', error); | ||
throw new Error('Authentication failed'); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Fetch paginated data from the specified collection in PocketBase. | ||
* @param collectionName The name of the collection to fetch data from. | ||
* @param batchSize The number of records to fetch per page. | ||
* @param onPageFetched Callback function to process fetched records. | ||
*/ | ||
export async function getCollectionData( | ||
collectionName: string, | ||
batchSize: number, | ||
onPageFetched: (data: RecordData[]) => void | ||
): Promise<void> { | ||
await authenticate(); | ||
|
||
try { | ||
const response = await pb.collection(collectionName).getList(1, batchSize, { | ||
sort: '-created', // Fetch the most recent records first | ||
}); | ||
|
||
if (response.items.length > 0) { | ||
onPageFetched(response.items); // Send data to the callback | ||
} else { | ||
console.warn(`No data found for collection: ${collectionName}`); | ||
} | ||
} catch (error) { | ||
console.error(`Error fetching data for collection ${collectionName}:`, error); | ||
} | ||
} | ||
|
||
/** | ||
* Subscribe to a collection in PocketBase for real-time updates. | ||
* @param collectionName The name of the collection to subscribe to. | ||
* @param callback Callback function to process new real-time updates. | ||
*/ | ||
export async function subscribeToCollection(collectionName: string, callback: (data: RecordData) => void) { | ||
await authenticate(); | ||
|
||
try { | ||
pb.collection(collectionName).subscribe('*', (e) => { | ||
if (e.record) { | ||
callback(e.record); | ||
} else { | ||
console.warn(`Received empty record in collection ${collectionName} real-time update.`); | ||
} | ||
}); | ||
console.log(`Subscribed to real-time updates for collection: ${collectionName}`); | ||
} catch (error) { | ||
console.error(`Error subscribing to collection ${collectionName}:`, error); | ||
} | ||
} | ||
|
||
/** | ||
* Unsubscribe from a collection in PocketBase to stop real-time updates. | ||
* @param collectionName The name of the collection to unsubscribe from. | ||
*/ | ||
export function unsubscribeFromCollection(collectionName: string) { | ||
try { | ||
pb.collection(collectionName).unsubscribe('*'); | ||
console.log(`Unsubscribed from real-time updates for collection: ${collectionName}`); | ||
} catch (error) { | ||
console.error(`Error unsubscribing from collection ${collectionName}:`, error); | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
<!DOCTYPE html> | ||
<!doctype html> | ||
<html lang="en" class="dark"> | ||
<head> | ||
<meta charset="utf-8" /> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
// data.ts | ||
import PocketBase from 'pocketbase'; | ||
|
||
|
||
const ADMIN_EMAIL: string = import.meta.env.VITE_EMAIL; | ||
const ADMIN_PASSWORD: string = import.meta.env.VITE_PASSWORD; | ||
|
||
|
||
const pb = new PocketBase('http://127.0.0.1:8090'); | ||
pb.autoCancellation(false); | ||
|
||
let isAuthenticated = false; | ||
|
||
|
||
|
||
// Function to authenticate the admin user | ||
export async function authenticate() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Authentication as well as subscribing is handled in usePocketbase hook (which may need some additions) in master so refactor to use that. Also, when using the hook we should make sure to pass around a global instance so that we are not opening duplicate pb connections like in this file. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have to refactor my code to incorporate the usePocketbase hook now will I will be implementing soon! |
||
if (!isAuthenticated) { | ||
await pb.admins.authWithPassword(ADMIN_EMAIL, ADMIN_PASSWORD); | ||
isAuthenticated = true; | ||
} | ||
} | ||
|
||
type RecordData = { [key: string]: any }; | ||
export type AllData = { [collectionName: string]: RecordData[] }; | ||
|
||
// Fetch paginated data with existing logic | ||
export async function fetchPaginatedData( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be extracted into its own hook that depends on |
||
collectionName: string, | ||
sendToChart: (data: RecordData[]) => void, | ||
batchSize: number = 10 | ||
) { | ||
console.log(`Fetching data from collection: ${collectionName}`); | ||
let page = 1; | ||
let hasMoreData = true; | ||
|
||
try { | ||
await authenticate(); // Authenticate once before fetching data | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe we only need to authenticate once, not every time we want to read/write to/from pocketbase. |
||
|
||
while (hasMoreData) { | ||
console.log('Fetching data from collection:', collectionName, 'Page:', page); | ||
const records = await pb.collection(collectionName).getList(page, batchSize); | ||
console.log('Fetched records:', records.items); | ||
|
||
if (records.items.length === 0) { | ||
console.warn(`No records found for ${collectionName} on page ${page}.`); | ||
break; | ||
} | ||
|
||
const dynamicKeys = Object.keys(records.items[0]).filter(key => key !== 'id' && key !== 'created'); | ||
|
||
const transformedBatch: RecordData[] = records.items.map((record: RecordData) => { | ||
const transformedRecord: RecordData = {}; | ||
dynamicKeys.forEach(key => { | ||
transformedRecord[key] = record[key]; | ||
}); | ||
return transformedRecord; | ||
}); | ||
|
||
console.log('Transformed batch:', transformedBatch); | ||
sendToChart(transformedBatch); | ||
|
||
if (records.items.length < batchSize) { | ||
hasMoreData = false; | ||
} else { | ||
page += 1; | ||
} | ||
} | ||
console.log('All data fetched for collection:', collectionName); | ||
} catch (error) { | ||
console.error('Error fetching paginated data for collection:', collectionName, error); | ||
} | ||
} | ||
|
||
// Real-time subscription to a collection | ||
export async function subscribeToCollection( | ||
collectionName: string, | ||
handleDataUpdate: (data: RecordData) => void | ||
) { | ||
try { | ||
await authenticate(); // Ensure we're authenticated before subscribing | ||
|
||
// Subscribe to the collection for any changes | ||
pb.collection(collectionName).subscribe('*', function (e) { | ||
console.log(`Received real-time update for collection ${collectionName}:`, e.record); | ||
handleDataUpdate(e.record); | ||
}); | ||
|
||
console.log(`Subscribed to real-time updates for collection: ${collectionName}`); | ||
} catch (error) { | ||
console.error(`Error subscribing to collection ${collectionName}:`, error); | ||
} | ||
} | ||
|
||
// Function to unsubscribe from a collection (optional) | ||
export async function unsubscribeFromCollection(collectionName: string) { | ||
try { | ||
await authenticate(); // Ensure we're authenticated before unsubscribing | ||
|
||
// Unsubscribe from the collection | ||
pb.collection(collectionName).unsubscribe('*'); | ||
|
||
console.log(`Unsubscribed from real-time updates for collection: ${collectionName}`); | ||
} catch (error) { | ||
console.error(`Error unsubscribing from collection ${collectionName}:`, error); | ||
} | ||
} |
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<script lang="ts" context="module"> | ||
export type PausablePromptResponse = ["submit" | "cancel" | "pause" | undefined, string]; | ||
</script> | ||
|
||
<script lang="ts"> | ||
import { getModalStore } from '@skeletonlabs/skeleton'; | ||
|
||
const modalStore = getModalStore(); | ||
|
||
export let heading: string = ""; | ||
let inputValue: string = ""; | ||
|
||
const finish = (value: PausablePromptResponse) => { | ||
$modalStore[0]?.response!(value); | ||
modalStore.close(); | ||
} | ||
|
||
const submit = () => { | ||
finish(["submit", inputValue]); | ||
} | ||
|
||
const pause = () => { | ||
finish(["pause", inputValue]); | ||
} | ||
|
||
const cancel = () => { | ||
finish(["cancel", ""]); | ||
} | ||
</script> | ||
|
||
<div class="modal block overflow-y-auto bg-surface-100-800-token w-modal h-auto p-4 space-y-4 rounded-container-token shadow-xl"> | ||
<header class="modal-header text-2xl font-bold">{heading}</header> | ||
<input class="modal-prompt-input input" bind:value={inputValue} type="text" /> | ||
<footer class="modal-footer flex justify-end space-x-2"> | ||
<button class="btn variant-ghost-surface" type="submit" on:click={cancel}>Cancel</button> | ||
<button class="btn variant-filled" type="submit" on:click={pause}>Pause</button> | ||
<button class="btn variant-filled" type="submit" on:click={submit}>Submit</button> | ||
</footer> | ||
</div> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<svg width="20px" height="20px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="#000000"> | ||
<g id="SVGRepo_bgCarrier" stroke-width="0"/> | ||
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/> | ||
<g id="SVGRepo_iconCarrier"> <!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools --> <title>ic_fluent_read_only_24_regular</title> <desc>Created with Sketch.</desc> <g id="🔍-System-Icons" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g id="ic_fluent_read_only_24_regular" fill="#d4163c" fill-rule="nonzero"> <path d="M3.28046,2.21962 L21.7802,20.7198 C22.0731,21.0127 22.0731,21.4875 21.7802,21.7804 C21.4873,22.0733 21.0125,22.0733 20.7196,21.7804 L14,15.0608 L9.0621,19.9987 C8.78522,20.2756 8.44089,20.4754 8.06312,20.5784 L2.94743,21.9736 C2.38756,22.1263 1.87383,21.6126 2.02652,21.0527 L3.42171,15.937 C3.52474,15.5593 3.72456,15.2149 4.00144,14.9381 L8.93944,10.0001 L2.21979,3.28027 C1.9269,2.98737 1.9269,2.5125 2.2198,2.21961 C2.51269,1.92672 2.98757,1.92672 3.28046,2.21962 Z M10.0001,11.0607 L5.0621,15.9987 C4.9928825,16.067925 4.93811,16.1498063 4.90056266,16.2395344 L4.86886,16.3317 L3.81901,20.1811 L7.66845,19.1313 C7.76289,19.105575 7.85106375,19.061625 7.92818297,19.0023609 L8.00144,18.9381 L12.9392,13.9999 L10.0001,11.0607 Z M15.9698,2.96973 C17.3672,1.57227 19.633,1.57227 21.0304,2.96973 C22.3779893,4.31728071 22.4261175,6.47219893 21.1747846,7.87741875 L21.0304,8.03039 L16.1207,12.9401 L15.0598,11.8793 L17.9393,8.99963 L15.0003,6.06063 L12.1207,8.94013 L11.0601,7.87943 L15.9698,2.96973 Z M17.0304,4.03039 L16.0603,4.99963 L18.9993,7.93963 L19.9698,6.96973 C20.7814,6.15805 20.7814,4.84206 19.9698,4.03039 C19.1581,3.21871 17.8421,3.21871 17.0304,4.03039 Z" id="🎨-Color"> </path> </g> </g> </g> | ||
</svg> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to change back to the PI IP
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, will do!