Skip to content

Commit 49ade36

Browse files
fix: fix state updates by using manual Refs to update computed values
1 parent 4f4f710 commit 49ade36

File tree

3 files changed

+136
-24
lines changed

3 files changed

+136
-24
lines changed

apps/lisa/public/auth.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
:root {
2+
--shared-auth-app-header-bar-background-color-from: #2e399e;
3+
--shared-auth-app-header-bar-background-color-to: #00c6ff;
4+
}

apps/lisa/src/components/DemandProcessor.vue

Lines changed: 130 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22
<div v-show="tabState === currentDemandState" v-if="currentState!== STATES.NoOperation">
3-
<Card>
3+
<Card :data-demand-id="demandUri">
44
<template #content>
55
<div class="grid">
66
<div class="col-12" v-if ="currentState === STATES.Terminated" >
@@ -145,8 +145,6 @@ const toast = useToast();
145145
const appMemory = useCache();
146146
const {session} = useSolidSession();
147147
148-
149-
150148
let businessDataFetched = ref(false);
151149
const enteredAnnualPercentageRate = ref(1.08);
152150
const selectedLoanTerm = ref({label: "60 months", value: "5"});
@@ -175,13 +173,62 @@ const shapeTrees = [
175173
}
176174
];
177175
176+
/**
177+
* Reactive state variable, but keep in mind, that something changes internally, Vuejs is not able to
178+
* recognize these changes, probably due to some private property changes. For example, if you use
179+
* store.addQuads(...) or store.add(...) the state won't be updating any computed reference / watcher,
180+
* that relies on that store.
181+
*/
178182
const state = reactive({
179183
demandStore: new Store(),
180184
offerStore: new Store(),
181185
orderStore: new Store(),
182186
demanderStore: new Store(),
183-
businessAssessmentStore : new Store()
187+
businessAssessmentStore : new Store(),
184188
});
189+
/**
190+
* change this if `state.demandStore` was changed somewhere.
191+
* E.g. by using `state.demandStore.addQuads(...);`
192+
*/
193+
const demandStoreChanges = ref(0);
194+
/**
195+
* change this if `state.offerStore` was changed somewhere.
196+
* E.g. by using `state.offerStore.addQuads(...);`
197+
*/
198+
const offerStoreChanges = ref(0);
199+
/**
200+
* change this if `state.orderStore` was changed somewhere.
201+
* E.g. by using `state.orderStore.addQuads(...);`
202+
*/
203+
const orderStoreChanges = ref(0);
204+
/**
205+
* change this if `state.demanderStore` was changed somewhere.
206+
* E.g. by using `state.demanderStore.addQuads(...);`
207+
*/
208+
const demanderStoreChanges = ref(0);
209+
/**
210+
* change this if `state.businessAssessmentStore` was changed somewhere.
211+
* E.g. by using `state.businessAssessmentStore.addQuads(...);`
212+
*/
213+
const businessAssessmentStoreChanges = ref(0);
214+
215+
/**
216+
* call this function with whatever you want to be tracked by vue-js.
217+
* Note, the function does not do anything! It is a no-op function.
218+
*
219+
* Usage:
220+
* ```typescript
221+
* const someRef = computed(() => {
222+
* track(someDependencyThatNeedsToBeExplicitlyTrackedHere.value);
223+
* return someOtherDependencyThatIsMayBeNotTrackedCorrectly;
224+
* });
225+
* ```
226+
*
227+
* You can pass multiple arguments, signals and variables to this function.
228+
*
229+
* @param _args anything you want to track by vue
230+
*/
231+
function track(..._args: unknown[]): void {}
185232
186233
async function fetchStoreOf(uri: string): Promise<Store> {
187234
return getResource(uri, session)
@@ -199,13 +246,15 @@ async function fetchStoreOf(uri: string): Promise<Store> {
199246
.then((parsedN3) => parsedN3.store);
200247
}
201248
202-
async function fillItemStoresIntoStore(itemUris: string[], store: Store, flag?:Ref<boolean> ) {
249+
async function fillItemStoresIntoStore(itemUris: string[], store: Store, flag?:Ref<boolean>
250+
) {
203251
const itemStores: Store[] = await Promise.all(
204252
itemUris.map((item) => fetchStoreOf(item))
205253
)
206254
itemStores
207255
.map(itemStore => itemStore.getQuads(null, null, null, null))
208-
.map((quads) => store.addQuads(quads))
256+
.forEach((quads) => store.addQuads(quads));
257+
209258
if(flag != undefined)
210259
{
211260
flag.value = !flag.value
@@ -214,46 +263,98 @@ async function fillItemStoresIntoStore(itemUris: string[], store: Store, flag?:R
214263
215264
function refreshState() {
216265
state.demandStore = new Store()
266+
demandStoreChanges.value += 1;
267+
fetchStoreOf(props.demandUri)
268+
.then(store => {
269+
state.demandStore = store;
270+
demandStoreChanges.value += 1;
271+
})
272+
217273
state.offerStore = new Store()
274+
offerStoreChanges.value += 1;
275+
218276
state.orderStore = new Store()
277+
orderStoreChanges.value += 1;
278+
219279
state.demanderStore = new Store()
220-
fetchStoreOf(props.demandUri).then(store => state.demandStore = store)
280+
demanderStoreChanges.value += 1;
221281
}
222282
223283
// DEMAND
224284
state.demandStore = await fetchStoreOf(props.demandUri);
225-
const accessRequestUri = computed(() => state.demandStore.getQuads(props.demandUri, CREDIT("hasAccessRequest"), null, null)[0]?.object?.value);
226-
const isAccessRequestGranted = computed(() => state.demandStore.getQuads(props.demandUri, CREDIT("isAccessRequestGranted"), null, null)[0]?.object?.value);
227-
const amount = computed(() => state.demandStore.getObjects(null, SCHEMA("amount"), null)[0]?.value);
228-
const currency = computed(() => state.demandStore.getObjects(null, SCHEMA("currency"), null)[0]?.value);
229-
const demanderUri = computed(() => state.demandStore.getQuads(null, SCHEMA("seeks"), props.demandUri, null)[0]?.subject?.value);
285+
demandStoreChanges.value += 1;
286+
287+
const accessRequestUri = computed(() => {
288+
track(demandStoreChanges.value);
289+
return state.demandStore.getQuads(props.demandUri, CREDIT("hasAccessRequest"), null, null)[0]?.object?.value
290+
});
291+
const isAccessRequestGranted = computed(() => {
292+
track(demandStoreChanges.value);
293+
return state.demandStore.getQuads(props.demandUri, CREDIT("isAccessRequestGranted"), null, null)[0]?.object?.value
294+
});
295+
const amount = computed(() => {
296+
track(demandStoreChanges.value);
297+
return state.demandStore.getObjects(null, SCHEMA("amount"), null)[0]?.value
298+
});
299+
const currency = computed(() => {
300+
track(demandStoreChanges.value);
301+
return state.demandStore.getObjects(null, SCHEMA("currency"), null)[0]?.value
302+
});
303+
const demanderUri = computed(() => {
304+
track(demandStoreChanges.value);
305+
return state.demandStore.getQuads(null, SCHEMA("seeks"), props.demandUri, null)[0]?.subject?.value
306+
});
230307
let currentDemandState= ref('Demand');
231308
// DEMANDER
232309
watch(() => demanderUri.value,
233310
async () => {
234311
if (demanderUri.value) {
235312
state.demanderStore =
236313
await fetchStoreOf(demanderUri.value)
314+
demanderStoreChanges.value += 1;
237315
}
238316
}, {immediate: true}
239317
)
240318
watch(()=> props.demandState,()=> {
241319
currentDemandState.value = props.demandState;
242320
}, {immediate:true});
243-
const demanderName = computed(() => state.demanderStore.getObjects(null, FOAF("name"), null)[0]?.value);
244-
const demanderIconUri = computed(() => state.demanderStore.getObjects(null, VCARD("hasPhoto"), null)[0]?.value);
245-
const demanderAccessInboxUri = computed(() => state.demanderStore.getObjects(null, INTEROP("hasAccessInbox"), null)[0]?.value);
321+
const demanderName = computed(() => {
322+
track(demanderStoreChanges.value);
323+
return state.demanderStore.getObjects(null, FOAF("name"), null)[0]?.value
324+
});
325+
const demanderIconUri = computed(() => {
326+
track(demanderStoreChanges.value);
327+
return state.demanderStore.getObjects(null, VCARD("hasPhoto"), null)[0]?.value
328+
});
329+
const demanderAccessInboxUri = computed(() => {
330+
track(demanderStoreChanges.value);
331+
return state.demanderStore.getObjects(null, INTEROP("hasAccessInbox"), null)[0]?.value
332+
});
246333
247334
// OFFER
248335
const orderStoreFilledFlag = ref(false)
249-
const offersForDemand = computed(() => state.demandStore.getObjects(props.demandUri, CREDIT("hasOffer"), null).map(term => term.value));
336+
const offersForDemand = computed(() => {
337+
track(demandStoreChanges.value);
338+
return state.demandStore.getObjects(props.demandUri, CREDIT("hasOffer"), null).map(term => term.value)
339+
});
250340
const isOfferCreated = computed(() => offersForDemand.value.length > 0);
251341
252342
await fillItemStoresIntoStore(offersForDemand.value, state.offerStore, orderStoreFilledFlag)
253-
watch(() => offersForDemand.value, () => fillItemStoresIntoStore(offersForDemand.value, state.offerStore, orderStoreFilledFlag));
343+
offerStoreChanges.value += 1;
254344
255-
const offerIsAccessible = computed(() => state.offerStore.getObjects(null, CREDIT("isAccessRequestGranted"), null).map(term => term.value));
256-
const offerAccessRequests = computed(() => state.offerStore.getObjects(null, CREDIT("hasAccessRequest"), null).map(term => term.value));
345+
watch(() => offersForDemand.value, async () => {
346+
await fillItemStoresIntoStore(offersForDemand.value, state.offerStore, orderStoreFilledFlag);
347+
offerStoreChanges.value += 1;
348+
});
349+
350+
const offerIsAccessible = computed(() => {
351+
track(offerStoreChanges.value);
352+
return state.offerStore.getObjects(null, CREDIT("isAccessRequestGranted"), null).map(term => term.value)
353+
});
354+
const offerAccessRequests = computed(() => {
355+
track(offerStoreChanges.value);
356+
return state.offerStore.getObjects(null, CREDIT("hasAccessRequest"), null).map(term => term.value)
357+
});
257358
watch(() => offerAccessRequests.value,
258359
async () => {
259360
offerAccessRequests.value.forEach(accessRequestURI => {
@@ -315,17 +416,22 @@ const currentState = computed(() =>{
315416
// meh. this imposes unnecessary requests and memory, should be application wide, but it works and I dont care at this point anymore.
316417
watch(() => offersForDemand.value,
317418
async () => {
419+
track(orderStoreChanges.value);
318420
const orderContainers = await getDataRegistrationContainers(memberOf.value, orderShapeTreeUri, session);
319421
const orderItems = (await Promise.all(orderContainers.map(orderContainer => getContainerItems(orderContainer, session)))).flat()
320422
await fillItemStoresIntoStore(orderItems, state.orderStore, orderStoreFilledFlag)
321-
}, {immediate: true})
423+
orderStoreChanges.value += 1;
424+
}, {immediate: true});
425+
322426
const hasOrderForAnyOfferForThisDemand = computed(() => {
427+
track(orderStoreChanges.value);
323428
const acceptedOffers = state.orderStore.getQuads(null, SCHEMA("acceptedOffer"), null, null).map(quad => quad.object?.value)
324429
return offersForDemand.value.some(offer => acceptedOffers.includes(offer))
325430
});
326431
327432
const hasTerminatedOrder = ref(false);
328433
watch(() => orderStoreFilledFlag.value == true, () => {
434+
track(orderStoreChanges.value);
329435
let acceptedOrders : string[] = [];
330436
for (const offer of offersForDemand.value){
331437
acceptedOrders.push(...state.orderStore.getSubjects(SCHEMA("acceptedOffer"), new NamedNode(offer), null).map(subject => subject.value));
@@ -346,6 +452,7 @@ async function fetchProcessedData() {
346452
const businessAssessmentUri = await getDataRegistrationContainers(demanderUri.value!, selectedShapeTree.value.value, session);
347453
const items = await getContainerItems(businessAssessmentUri[0], session);
348454
await fillItemStoresIntoStore(items, state.businessAssessmentStore);
455+
businessAssessmentStoreChanges.value += 1;
349456
businessDataFetched.value = true;
350457
}
351458
@@ -557,7 +664,7 @@ async function createOfferResource(demand: string, dataAccessRequest: string) {
557664
offerAccessRequests.value.forEach(function (offerAccessRequest) {
558665
handleAuthorizationRequest(offerAccessRequest)
559666
});
560-
},5000);
667+
}, 5000);
561668
562669
}
563670
@@ -582,7 +689,7 @@ function handleAuthorizationRequest(inspectedAccessRequestURI: string) {
582689
inspectedAccessRequestURI
583690
)}&app_redirect=${encodeURIComponent(
584691
window.location.origin + "/accessRequestHandled"
585-
)}`,
692+
)}&css=${encodeURIComponent(window.location.origin + "/auth.css")}`,
586693
"_self"
587694
);
588695
}
@@ -628,7 +735,7 @@ async function handleAuthorizationRequestRedirect(
628735
}
629736
setTimeout(()=>{
630737
const id = props.demandUri.slice(props.demandUri.lastIndexOf('/')+1);
631-
const data:demandData ={
738+
const data = {
632739
"id": id,
633740
"name": demanderName.value,
634741
"status": currentState.value,

apps/tom/src/views/Demands.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,8 @@ function handleAuthorizationRequest(inspectedAccessRequestURI: string) {
392392
<ProgressBar v-show="isLoading" mode="indeterminate" style="height: 2px" />
393393

394394
<div role="list" v-if="displayedDemands" class="flex flex-column gap-3 py-0 px-3">
395-
<Card :class="{'bg-yellow-100' : highlightAmountValue === demand.amount, ['amount-'+demand.amount]: true }" role="listitem" v-for="demand in displayedDemands" :key="demand.id">
395+
<Card :class="{'bg-yellow-100' : highlightAmountValue === demand.amount, ['amount-'+demand.amount]: true }"
396+
role="listitem" v-for="demand in displayedDemands" :key="demand.id" :data-demand-id="demand.id">
396397
<template #title>
397398
<a class="font-normal text-black-alpha-90 no-underline" :href="demand.providerWebID">{{ demand.providerName }}</a>
398399
</template>

0 commit comments

Comments
 (0)