Skip to content

Commit

Permalink
feat: fire properties have low/high and input suggestions
Browse files Browse the repository at this point in the history
  • Loading branch information
ymarcon committed Dec 18, 2024
1 parent db0474d commit 7a65626
Show file tree
Hide file tree
Showing 8 changed files with 268 additions and 36 deletions.
89 changes: 65 additions & 24 deletions admin/src/components/PhysicalEntityForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
<div class="text-bold q-mb-sm">{{ $t('structural') }}</div>
<div class="row q-col-gutter-lg">
<div class="col">
<property-form-item
<property-form-number
v-for="property in ['density', 'compressive_strength', 'tensile_strength']"
:key="property"
v-model="entity"
:property="property"
/>
</div>
<div class="col">
<property-form-item
<property-form-number
v-for="property in ['youngs_modulus', 'shrinkage', 'settlement']"
:key="property"
v-model="entity"
Expand All @@ -22,7 +22,7 @@
<div class="text-bold q-mb-sm">{{ $t('hygrothermal') }}</div>
<div class="row q-col-gutter-lg">
<div class="col">
<property-form-item
<property-form-number
v-for="property in [
'thermal_conductivity',
'thermal_capacity',
Expand All @@ -35,7 +35,7 @@
/>
</div>
<div class="col">
<property-form-item
<property-form-number
v-for="property in ['u', 'effusivity', 'diffusivity']"
:key="property"
v-model="entity"
Expand All @@ -46,7 +46,7 @@
<div class="text-bold q-mb-sm">{{ $t('acoustic') }}</div>
<div class="row q-col-gutter-lg">
<div class="col">
<property-form-item
<property-form-number
v-for="property in ['absorption_coefficient', 'sound_reduction_index']"
:key="property"
v-model="entity"
Expand All @@ -58,33 +58,26 @@
<div class="text-bold q-mb-sm">{{ $t('fire') }}</div>
<div class="row q-col-gutter-lg">
<div class="col">
<property-form-item
v-for="property in ['reaction_to_fire']"
:key="property"
<property-form-suggest
v-model="entity"
:property="property"
:options="reactionToFireClasses"
:property="'reaction_to_fire'"
:suggestions="reactionToFireClasses"
@suggest="onSuggest"
/>
</div>
<div class="col">
<property-form-item
v-for="property in ['fire_resistance_class']"
:key="property"
<property-form-suggest
v-model="entity"
:property="property"
:options="fireResistanceClasses"
:property="'fire_resistance_class'"
:suggestions="fireResistanceClasses"
@suggest="onSuggest"
/>
</div>
</div>
<div class="text-bold q-mb-sm">{{ $t('others') }}</div>
<div class="row q-col-gutter-lg">
<div class="col">
<property-form-item
v-for="property in ['air_tightness']"
:key="property"
v-model="entity"
:property="property"
/>
<property-form-item v-model="entity" :property="'air_tightness'" />
</div>
<div class="col"></div>
</div>
Expand All @@ -98,7 +91,9 @@ export default defineComponent({
</script>
<script setup lang="ts">
import { PhysicalEntity } from 'src/models';
import PropertyFormItem from 'src/components/PropertyFormItem.vue';
import PropertyFormNumber from 'src/components/PropertyFormNumber.vue';
import PropertyFormSuggest from 'src/components/PropertyFormSuggest.vue';
import { Suggestions } from 'src/components/models';
interface Props {
modelValue: PhysicalEntity;
Expand All @@ -108,13 +103,59 @@ const props = defineProps<Props>();
const entity = ref(props.modelValue);
const reactionToFireClasses = ['A1', 'A2', 'B', 'C', 'D', 'E', 'F'];
const fireResistanceClasses = ['R', 'RE', 'REI', 'EI'];
const reactionToFireClasses = ref<Suggestions>({});
const fireResistanceClasses = ref<Suggestions>({});
watch(
() => props.modelValue,
(val) => {
entity.value = val;
},
);
function onSuggest(property: string, key: string, value: string) {
let suggestions: string[] = [];
if (property === 'reaction_to_fire') {
// format suggested: <A1|A2|B|C|D|E|F>-<S1|S2|S3>-<D0|D1|D2>
const base = ['A1', 'A2', 'B', 'C', 'D', 'E', 'F'];
if (value && base.find((cls) => value.startsWith(cls))) {
const tokens = value.split('-');
const smoke = ['S1', 'S2', 'S3'];
const droplets = ['D0', 'D1', 'D2'];
// if value does not contain smoke
if (tokens.length > 1 && !smoke.find((cls) => tokens[1].trim().includes(cls))) {
suggestions = smoke.map((s) => `${tokens[0].trim()}-${s}`);
} else if (tokens.length > 2 && !droplets.find((cls) => tokens[2].trim().includes(cls))) {
suggestions = droplets.map((d) => `${tokens[0].trim()}-${tokens[1].trim()}-${d}`);
} else {
suggestions = base;
}
} else {
suggestions = base;
}
reactionToFireClasses.value = {
key,
options: suggestions,
};
}
if (property === 'fire_resistance_class') {
// format suggested: <R|RE|REI|EI>-<30|60|90|120>
const base = ['R', 'RE', 'REI', 'EI'];
if (value && base.find((cls) => value.startsWith(cls))) {
const tokens = value.split('-');
const time = ['30', '60', '90', '120'];
if (tokens.length > 1 && !time.find((cls) => tokens[1].trim().includes(cls))) {
suggestions = time.map((t) => `${tokens[0].trim()}-${t}`);
} else {
suggestions = base;
}
} else {
suggestions = base;
}
fireResistanceClasses.value = {
key,
options: suggestions,
};
}
}
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,7 @@
<div class="q-mb-sm">
{{ $t(property) }}
</div>
<div v-if="options">
<q-select
filled
v-model="selected[property]"
:label="$t('class')"
:options="options"
@update:model-value="onUpdate(property)"
/>
</div>
<div v-else class="row q-col-gutter-sm q-mb-sm">
<div class="row q-col-gutter-sm q-mb-sm">
<div class="col">
<q-input
filled
Expand Down Expand Up @@ -49,7 +40,7 @@

<script lang="ts">
export default defineComponent({
name: 'PropertyFormItem',
name: 'PropertyFormNumber',
});
</script>
<script setup lang="ts">
Expand All @@ -58,7 +49,6 @@ import { PhysicalEntity } from 'src/models';
interface Props {
modelValue: PhysicalEntity;
property: string;
options?: string[];
}
const props = defineProps<Props>();
Expand Down
120 changes: 120 additions & 0 deletions admin/src/components/PropertyFormSuggest.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<template>
<div>
<div class="q-mb-sm">
{{ $t(property) }}
</div>

<div class="row q-col-gutter-sm q-mb-sm">
<div class="col">
<q-input
filled
v-model="selected[`${property}_low`]"
:label="$t('low')"
@update:model-value="onUpdate(`${property}_low`)"
>
<q-menu v-model="showLowSuggestions" no-parent-event no-focus auto-close>
<q-list style="min-width: 100px">
<q-item
clickable
v-close-popup
v-for="sugg in suggestions.options"
:key="sugg"
@click="selected[`${property}_low`] = sugg"
>
<q-item-section>{{ sugg }}</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-input>
</div>
<div class="col">
<q-input filled v-model="selected[property]" :label="$t('std')" @update:model-value="onUpdate(property)">
<q-menu v-model="showStdSuggestions" no-parent-event no-focus auto-close>
<q-list style="min-width: 100px">
<q-item
clickable
v-close-popup
v-for="sugg in suggestions.options"
:key="sugg"
@click="selected[property] = sugg"
>
<q-item-section>{{ sugg }}</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-input>
</div>
<div class="col">
<q-input
filled
v-model="selected[`${property}_high`]"
:label="$t('high')"
@update:model-value="onUpdate(`${property}_high`)"
>
<q-menu v-model="showHighSuggestions" no-parent-event no-focus auto-close>
<q-list style="min-width: 100px">
<q-item
clickable
v-close-popup
v-for="sugg in suggestions.options"
:key="sugg"
@click="selected[`${property}_high`] = sugg"
>
<q-item-section>{{ sugg }}</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-input>
</div>
</div>
<div class="q-mb-md text-hint">
{{ $t(`${property}_hint`) }}
</div>
</div>
</template>

<script lang="ts">
export default defineComponent({
name: 'PropertyFormSuggest',
});
</script>
<script setup lang="ts">
import { PhysicalEntity } from 'src/models';
import { Suggestions } from 'src/components/models';
interface Props {
modelValue: PhysicalEntity;
property: string;
suggestions?: Suggestions;
}
const props = defineProps<Props>();
const emits = defineEmits(['suggest']);
const showLowSuggestions = ref(false);
const showStdSuggestions = ref(false);
const showHighSuggestions = ref(false);
const selected = ref(props.modelValue);
watch(
() => props.suggestions,
(val) => {
if (val) {
showLowSuggestions.value = val.key.endsWith('_low');
showHighSuggestions.value = val.key.endsWith('_high');
showStdSuggestions.value = !showLowSuggestions.value && !showHighSuggestions.value;
} else {
showLowSuggestions.value = false;
showHighSuggestions.value = false;
showStdSuggestions.value = false;
}
},
);
function onUpdate(key: string) {
if (selected.value[key] === '') {
selected.value[key] = null;
}
emits('suggest', props.property, key, selected.value[key]);
}
</script>
5 changes: 5 additions & 0 deletions admin/src/components/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,8 @@ export interface Option {
label: string;
level?: number;
}

export interface Suggestions {
key: string;
options: string[];
}
4 changes: 4 additions & 0 deletions admin/src/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ export interface PhysicalEntity extends Entity {
diffusivity_low?: number;
absorption_coefficient_low?: number;
sound_reduction_index_low?: number;
reaction_to_fire_low?: string;
fire_resistance_class_low?: string;
air_tightness_low?: number;

density_high?: number;
Expand All @@ -96,6 +98,8 @@ export interface PhysicalEntity extends Entity {
diffusivity_high?: number;
absorption_coefficient_high?: number;
sound_reduction_index_high?: number;
reaction_to_fire_high?: string;
fire_resistance_class_high?: string;
air_tightness_high?: number;
}

Expand Down
4 changes: 4 additions & 0 deletions backend/api/models/domain.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ class PhysicalEntity(Entity):
diffusivity_low: Optional[float] = Field(default=None)
absorption_coefficient_low: Optional[float] = Field(default=None)
sound_reduction_index_low: Optional[float] = Field(default=None)
reaction_to_fire_low: Optional[str] = Field(default=None)
fire_resistance_class_low: Optional[str] = Field(default=None)
air_tightness_low: Optional[float] = Field(default=None)

density_high: Optional[float] = Field(default=None)
Expand All @@ -82,6 +84,8 @@ class PhysicalEntity(Entity):
diffusivity_high: Optional[float] = Field(default=None)
absorption_coefficient_high: Optional[float] = Field(default=None)
sound_reduction_index_high: Optional[float] = Field(default=None)
reaction_to_fire_high: Optional[str] = Field(default=None)
fire_resistance_class_high: Optional[str] = Field(default=None)
air_tightness_high: Optional[float] = Field(default=None)

# Association tables
Expand Down
Loading

0 comments on commit 7a65626

Please sign in to comment.