Skip to content

Commit

Permalink
fix(#9): FE - Refactor UI and added missing test
Browse files Browse the repository at this point in the history
  • Loading branch information
tholulomo committed Oct 14, 2023
1 parent 4f71e58 commit 98474de
Show file tree
Hide file tree
Showing 36 changed files with 3,950 additions and 383 deletions.
157 changes: 157 additions & 0 deletions app/src/components/metamine/visualizationNU/DataSelector.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
<template>
<div class="data-selector-wrapper">
<div class="data-row">
<div class="article_metadata_strong md-title">Data</div>
<md-table class="u_width--max u_divider-fullspan utility-transparentbg viz-u-postion__rel viz-u-zIndex__min"
v-model="fetchedNames" @md-selected="onSelect" :md-selected-value="selectedValue" >
<md-table-empty-state md-label="No data available">
</md-table-empty-state>
<template #md-table-row="{ item }">
<md-table-row md-selectable="multiple" md-auto-select md-default-selected :key="item.name" >
<md-table-cell md-label="Name" md-sort-by="name">
<md-chip md-clickable :style="{'background-color': item.color, color: 'white'}">{{ item.name }}</md-chip>
</md-table-cell>
</md-table-row>
</template>
</md-table>
</div>
<div v-if="page === 'scatter'">
<div class="u--layout-flex u--layout-flex-column" style="margin: 5px 0px">
<md-field>
<label for="xAxis">X-axis</label>
<md-select class="u_width--max" v-model="query1" name="xAxis">
<md-option value="C11">C11</md-option>
<md-option value="C12">C12</md-option>
<md-option value="C22">C22</md-option>
<md-option value="C16">C16</md-option>
<md-option value="C26">C26</md-option>
<md-option value="C66">C66</md-option>
</md-select>
</md-field>
</div>
<div class="u--layout-flex u--layout-flex-column" style="margin: 5px 0px">
<md-field>
<label for="yAxis">Y-axis</label>
<md-select class="u_width--max" v-model="query2" name="yAxis">
<md-option value="C11">C11</md-option>
<md-option value="C12">C12</md-option>
<md-option value="C22">C22</md-option>
<md-option value="C16">C16</md-option>
<md-option value="C26">C26</md-option>
<md-option value="C66">C66</md-option>
</md-select>
</md-field>
</div>
</div>
<div v-if="page === 'hist'">
<div class="u--layout-flex u--layout-flex-column" style="margin: 5px 0px">
<md-field>
<label for="xAxis">X-axis</label>
<md-select v-model="query1" class="u_width--max" name="xAxis">
<md-option value="C11">C11</md-option>
<md-option value="C12">C12</md-option>
<md-option value="C22">C22</md-option>
<md-option value="C16">C16</md-option>
<md-option value="C26">C26</md-option>
<md-option value="C66">C66</md-option>
</md-select>
</md-field>
</div>
</div>
</div>
</template>

<script>
import { mapState } from 'vuex'
export default {
name: 'DataSelector',
mounted () {
if (!this.query1) {
this.handleQuery1Change(this.$route.query.pairwise_query1)
}
if (!this.query2) {
this.handleQuery2Change(this.$route.query.pairwise_query2)
}
},
computed: {
...mapState('metamineNU', {
activeData: (state) => state.activeData,
fetchedNames: (state) => state.fetchedNames,
dataLibrary: (state) => state.dataLibrary,
page: (state) => state.page,
query1: (state) => state.query1,
query2: (state) => state.query2
}),
selectedValue () {
return this.fetchedNames.filter((item) => this.activeData.map(data => data.name).includes(item.name))
}
},
watch: {
fetchedNames: {
handler: function (val, oldVal) {
this.data = val
this.selectedRowKeys = val.map((item) => item.key)
},
deep: true
},
activeData: {
handler: function (val, oldVal) {
this.selectedRowKeys = this.fetchedNames
.map((item) => {
return val.map((d) => d.name).includes(item.name)
? item.key
: null
})
.filter((item) => item !== null)
},
deep: true
},
dataLibrary: {
handler: function (val, oldVal) {},
deep: true
}
},
methods: {
handleQuery1Change (value) {
this.$store.dispatch('metamineNU/setQuery1', value)
},
handleQuery2Change (value) {
this.$store.dispatch('metamineNU/setQuery2', value)
},
onSelect (items) {
const self = this
const selected = items
const unselected = this.fetchedNames.filter(
(item) => !selected.includes(item)
)
selected.map((dataNameObj, index) => {
let sourceItems = self.activeData
let destItems = self.dataLibrary
const checked = destItems.filter(
(item) => item.name === dataNameObj.name
)
destItems = destItems.filter(
(item) => item.name !== dataNameObj.name
)
sourceItems = [...sourceItems, ...checked]
self.$store.dispatch('metamineNU/setActiveData', sourceItems)
self.$store.dispatch('metamineNU/setDataLibrary', destItems)
})
unselected.map((dataNameObj, index) => {
let sourceItems = self.dataLibrary
let destItems = self.activeData
const unchecked = destItems.filter(
(item) => item.name === dataNameObj.name
)
destItems = destItems.filter(
(item) => item.name !== dataNameObj.name
)
sourceItems = [...sourceItems, ...unchecked]
self.$store.dispatch('metamineNU/setActiveData', destItems)
self.$store.dispatch('metamineNU/setDataLibrary', sourceItems)
})
}
}
}
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<template>
<div class="material-info-wrapper">
<div
style="font-size: 20px; font-weight: bold; padding: 0px"
>
Material Information
</div>
<div class="u_display-flex u_centralize_items ">
<div
style="background: 'white', border: '1px solid black', width: '10px', height: '10px'"
></div>
<h3 style="margin: '0 10px'">Constituent Material 0 Properties</h3>
</div>
<div class="u_display-flex u_centralize_items">Type: {{ dataPoint && dataPoint['CM0'] }}</div>
<div class="u_display-flex u_centralize_items">
Young's Modulus: {{ dataPoint && dataPoint['CM0_E'] }}
</div>
<div class="u_display-flex u_centralize_items">
Poisson's Ratio: {{ dataPoint && dataPoint['CM0_nu'] }}
</div>

<div class="u_display-flex u_centralize_items">
<div
style="background: 'black', border: '1px solid black', width: '10px', height: '10px'"
></div>
<h3 style="margin: '0 10px'">Constituent Material 1 Properties</h3>
</div>
<div class="u_display-flex u_centralize_items">Type: {{ dataPoint && dataPoint['CM1'] }}</div>
<div class="u_display-flex u_centralize_items">
Young's Modulus: {{ dataPoint && dataPoint['CM1_E'] }}
</div>
<div class="u_display-flex u_centralize_items">
Poisson's Ratio: {{ dataPoint && dataPoint['CM1_nu'] }}
</div>
</div>
</template>

<script>
import { mapState } from 'vuex'
export default {
name: 'MaterialInformation',
computed: {
...mapState('metamineNU', {
dataPoint: (state) => state.dataPoint
})
}
}
</script>
58 changes: 58 additions & 0 deletions app/src/components/metamine/visualizationNU/NeighborPanel.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<template>
<div class="neighbor-panel-wrapper">
<div
class="table-header u_display-flex u--layout-flex-justify-sb u_centralize_items">
<div class="nuplot-table-title article_metadata_strong md-title u--padding-zero">Nearest Neighbors Panel</div>
<md-button>
<download-csv :data="neighbors" name="five_nearest_neighbors.csv" >
Download Data <md-icon>download</md-icon>
</download-csv>
</md-button>
</div>
<md-table>
<md-table-row>
<md-table-cell v-for="neighbor in neighbors" :key="neighbor.index" >
<StructureKnnVue :dataPoint="neighbor" />
</md-table-cell>
</md-table-row>
<md-table-row v-for="column in columns" :key="column">
<md-table-cell v-for="neighbor in neighbors" :key="`${column}-${neighbor.index}`" style="font-size: 8px">
{{ column }}: {{ neighbor[column] }}
</md-table-cell>
</md-table-row>
</md-table>
</div>
</template>

<style scoped>
.neighbor-panel-wrapper {
width: fit-content;
}
</style>

<script>
import { mapState } from 'vuex'
import StructureKnnVue from '@/components/metamine/visualizationNU/StructureKnn.vue'
import JsonCSV from 'vue-json-csv'
const columns = ['C11', 'C12', 'C22', 'C16', 'C26', 'C66', 'distance']
export default {
name: 'NeighborPanel',
components: {
StructureKnnVue,
downloadCsv: JsonCSV
},
computed: {
...mapState('metamineNU', {
neighbors: (state) => state.neighbors
})
},
data () {
return {
columns: columns
}
}
}
</script>
85 changes: 85 additions & 0 deletions app/src/components/metamine/visualizationNU/ParamSelector.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<template>
<div>
<div class="md-title article_metadata_strong section_footer utility-transparentbg">
Hyperparameter
</div>
<div class="article_metadata_strong">Number of neighbors:</div>
<div style="width: 80%">
The size of local neighborhood (in terms of number of neighboring
sample points) used for manifold approximation. Larger values result
in more global views of the manifold, while smaller values result in
more local data being preserved. (Default: 15)
</div>
<div class="u_display-flex md-layout u--layout-flex-justify-sb tool_page">
<div class="md-layout-item md-size-80">
<div class="nuplot-range-slider u--margin-centered u_centralize_text viz-u-postion__rel">
<input
id="parame-selector-slider"
class="nuplot-range-slider u--margin-centered u_centralize_text viz-u-postion__abs utility-transparentbg"
type="range"
min="5"
max="50"
step="1"
v-model="knnUmap"
@change="handleKnnUmapChange"
/>
<div class="u_display-flex u--layout-flex-justify-sb tools_box-content-odd" style="padding-top: 30px;">
<div class="u--color-grey-sec" v-for="tick in ticks" :key="tick" >
{{ tick }}
</div>
</div>
<div class="nuplot-slider-tooltip" id="parame-selector-slider-id"></div>
</div>
</div>
<div class="utility-roverflow md-layout-item md-size-20">
<md-field>
<md-input v-model="knnUmap" type="number" @change="handleKnnUmapChange" ></md-input>
</md-field>
</div>
</div>
</div>
</template>

<script>
import { mapState } from 'vuex'
export default {
name: 'ParamSelector',
mounted: () => {
const slider = document.getElementById('parame-selector-slider')
const tooltip = document.getElementById('parame-selector-slider-id')
slider.addEventListener('input', () => {
const value = parseInt(slider.value)
tooltip.textContent = value
tooltip.style.left = `calc(${((value - 5) / 45) * 100}% - 15px)`
})
slider.addEventListener('mousemove', (e) => {
const value = parseInt(slider.value)
tooltip.style.left = `calc(${((value - 5) / 45) * 100}% - 15px)`
tooltip.style.display = 'block'
tooltip.style.top = `-${tooltip.offsetHeight + 5}px`
})
slider.addEventListener('mouseout', () => {
tooltip.style.display = 'none'
})
},
computed: {
...mapState('metamineNU', {
knnUmap: (state) => state.knnUmap
})
},
data () {
return {
ticks: [5, 25, 50]
}
},
methods: {
handleKnnUmapChange (event) {
this.$store.dispatch('metamineNU/setKnnUmap', event.target.value)
}
}
}
</script>
Loading

0 comments on commit 98474de

Please sign in to comment.