Skip to content

Commit

Permalink
fix: bulk saves looking at wrong metadata to determine property relat…
Browse files Browse the repository at this point in the history
…ional role
  • Loading branch information
ascott18 committed May 28, 2024
1 parent 4f7832f commit 2e48a8e
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 18 deletions.
136 changes: 121 additions & 15 deletions playground/Coalesce.Web.Vue3/src/components/test-setup.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,54 @@
<template>
<div>
<span>123</span>
<v-btn @click="reset">Reset</v-btn>
<v-btn @click="person.companyId = null">Reset direct</v-btn>
<v-container>
<v-btn @click="add" prepend-icon="fa fa-plus"> Add Product </v-btn>
<v-btn
@click="vm.$bulkSave()"
:loading="vm.$bulkSave.isLoading"
prepend-icon="fa fa-save"
>
Save
</v-btn>
<v-btn
@click="vm.$load()"
:loading="vm.$load.isLoading"
prepend-icon="fa fa-sync"
>
Load
</v-btn>
<input
v-model="vm.caseKey"
:disabled="vm.caseKey && !vm.$getPropDirty('caseKey')"
placeholder="PK to load"
/>

<c-select :model="person" for="company"> </c-select>
<c-loader-status :loaders="{ '': [vm.$bulkSave] }"></c-loader-status>
<h2>Case (pk: {{ vm.$primaryKey }})</h2>

<v-btn @click="person.birthDate = null">Reset direct</v-btn>
<c-input :model="person" for="birthDate"> </c-input>
</div>
<c-input :model="vm" for="title"></c-input>
<c-input :model="vm" for="caseProducts"></c-input>
<div v-for="x in vm.caseProducts">
<v-btn
variant="text"
size="x-small"
@click="
x.product?.$remove();
x.product = null;
x.$remove();
"
icon="fa fa-trash"
></v-btn>
<v-btn
variant="text"
size="x-small"
@click="
x.product?.$remove();
x.product = newProduct();
"
icon="fa fa-sync"
></v-btn>
{{ x.product?.name }}: (pk: {{ x.$primaryKey }}, ref {{ x.$stableId }})
</div>
</v-container>
</template>

<script setup lang="ts">
Expand All @@ -20,15 +60,81 @@ import {
} from "@/viewmodels.g";
import { useBindToQueryString } from "coalesce-vue";
import { ref } from "vue";
import { useRouter } from "vue-router";
const router = useRouter();
// const vm = new CaseViewModel({title: 'asd'});
const vm = new CaseViewModel();
// vm.$load(1);
vm.assignedTo = new PersonViewModel({ firstName: "bob", companyId: 1 });
const person = new PersonViewModel();
person.arbitraryCollectionOfStrings = ["asdf"];
vm.$bulkSave.setConcurrency("debounce");
async function add() {
vm.addToCaseProducts({
product: newProduct(),
});
}
async function del() {
vm.caseProducts![0].$remove();
}
function newProduct() {
return new ProductViewModel({
name: products[Math.ceil(Math.random() * products.length) - 1],
});
}
const products = [
"JavaScript",
"Python",
"Java",
"C#",
"C++",
"Ruby",
"PHP",
"Swift",
"Go",
"TypeScript",
"Kotlin",
"Rust",
"Scala",
"Perl",
"HTML/CSS",
"SQL",
"Node.js",
"React.js",
"Angular",
"Vue.js",
"Django",
"Ruby on Rails",
"Spring Framework",
".NET Core",
"Express.js",
"TensorFlow",
"PyTorch",
"Unity",
"Elixir",
"GraphQL",
];
// const caseApiClient = new CaseApiClient();
// caseApiClient.bulkSave({
// "items": [
// { "type": "Case", action: 'save', "data": { "title": "asdf" }, "refs": {"assignedToId": 2}, root: true},
// { "type": "Person", action: 'save', "data": { "firstName": "bob", "companyId": 1 }, "refs": {"personId": 2}},
// { "type": "Case", action: 'save', "data": { "caseKey": 1, "title": "case 1" }},
// // { "type": "Person", action: 'delete', "data": { "personId": 2125 }}
// ],
// })
const firstName = ref("");
const lastName = ref("");
useBindToQueryString(firstName, "value", "firstName");
useBindToQueryString(lastName, "value", "lastName");
useBindToQueryString(person, "companyId", "companyId", parseInt, "replace");
function reset() {
router.replace({ query: {} });
function clearQueryStrings() {
// If both first & last name are set,
// only one of the query strings is removed
// from the URL bar
firstName.value = "";
lastName.value = "";
}
</script>
7 changes: 4 additions & 3 deletions src/IntelliTect.Coalesce/Api/Controllers/BaseApiController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,9 @@ IBehaviorsFactory behaviorsFactory
continue;
}

var referencedProp = item.ParamDtoClassViewModel.PropertyByName(reference.Key);
if (referencedProp is not { Role: PropertyRole.ForeignKey, IsClientWritable: true })
var referencedModelProp = item.DeclaredForClassViewModel.PropertyByName(reference.Key);
var referencedDtoProp = item.ParamDtoClassViewModel.PropertyByName(reference.Key);
if (referencedDtoProp is null || referencedModelProp is not { Role: PropertyRole.ForeignKey, IsClientWritable: true })
{
// Ignore invalid refs. We only need to resolve writable foreign keys.
continue;
Expand All @@ -214,7 +215,7 @@ IBehaviorsFactory behaviorsFactory
}

// Update the DTO with the new FK.
referencedProp.PropertyInfo.SetValue(item.Data, principalKey);
referencedDtoProp.PropertyInfo.SetValue(item.Data, principalKey);
}

// If we made it here, there were no refs preventing a save.
Expand Down

0 comments on commit 2e48a8e

Please sign in to comment.