Skip to content

Commit

Permalink
- ADD: Added color palette selector from pre-defined list.
Browse files Browse the repository at this point in the history
- CHG: Updated footer link to new GridScore website.
-
  • Loading branch information
sebastian-raubach committed Apr 26, 2024
1 parent a2ec11c commit 2a7f298
Show file tree
Hide file tree
Showing 15 changed files with 86 additions and 32 deletions.
2 changes: 1 addition & 1 deletion src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
</div>

<ul class="nav col-md-4 justify-content-center justify-content-md-end list-unstyled d-flex">
<li class="ml-3"><a class="text-muted" href="https://cropgeeks.github.io/gridscore-next-client"><BIconGlobe2 /></a></li>
<li class="ml-3"><a class="text-muted" href="https://ics.hutton.ac.uk/get-gridscore"><BIconGlobe2 /></a></li>
<li class="ml-3"><a class="text-muted" href="https://twitter.com/GerminateHub"><BIconTwitter /></a></li>
<li class="ml-3"><a class="text-muted" href="https://github.com/cropgeeks/gridscore-next-client"><BIconGithub /></a></li>
</ul>
Expand Down
2 changes: 1 addition & 1 deletion src/components/MarkerSetup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ export default {
}
// Draw the circle
this.ctx.fillStyle = this.storeTraitColors[1]
this.ctx.fillStyle = this.storeTraitColors[1 % this.storeTraitColors.length]
this.ctx.beginPath()
this.ctx.arc(finalX, finalY, 6, 0, 2 * Math.PI)
this.ctx.fill()
Expand Down
5 changes: 3 additions & 2 deletions src/components/charts/FieldHeatmap.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
import { mapGetters } from 'vuex'
import { getTrialDataCached } from '@/plugins/datastore'
import { CELL_CATEGORY_CONTROL, DISPLAY_ORDER_LEFT_TO_RIGHT, DISPLAY_ORDER_TOP_TO_BOTTOM } from '@/plugins/constants'
import { categoryColors, invertHex, toLocalDateString } from '@/plugins/misc'
import { invertHex, toLocalDateString } from '@/plugins/misc'
import { categoricalColors } from '@/plugins/color'
import PlotDataSection from '@/components/PlotDataSection'
const emitter = require('tiny-emitter/instance')
Expand Down Expand Up @@ -298,7 +299,7 @@ export default {
colorscale: this.selectedTrait.dataType === 'categorical'
? restrictions.categories.map((_, i) => {
const l = restrictions.categories.length
const c = categoryColors[i % categoryColors.length]
const c = categoricalColors.D3schemeCategory10[i % categoricalColors.D3schemeCategory10.length]
return [[i / l, c], [(i + 1) / l, c]]
}).flat()
: [[0, this.storeDarkMode ? '#444444' : '#dddddd'], [1, this.selectedTrait.color]],
Expand Down
5 changes: 3 additions & 2 deletions src/components/charts/GermplasmRepHeatmap.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
<script>
import { mapGetters } from 'vuex'
import { getTrialDataCached } from '@/plugins/datastore'
import { categoryColors, invertHex, toLocalDateString } from '@/plugins/misc'
import { invertHex, toLocalDateString } from '@/plugins/misc'
import { categoricalColors } from '@/plugins/color'
import PlotDataSection from '@/components/PlotDataSection'
import { CELL_CATEGORY_CONTROL } from '@/plugins/constants'
Expand Down Expand Up @@ -313,7 +314,7 @@ export default {
colorscale: this.selectedTrait.dataType === 'categorical'
? restrictions.categories.map((_, i) => {
const l = restrictions.categories.length
const c = categoryColors[i % categoryColors.length]
const c = categoricalColors.D3schemeCategory10[i % categoricalColors.D3schemeCategory10.length]
return [[i / l, c], [(i + 1) / l, c]]
}).flat()
: [[0, this.storeDarkMode ? '#444444' : '#dddddd'], [1, this.selectedTrait.color]],
Expand Down
8 changes: 4 additions & 4 deletions src/components/modals/EditPeopleModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,22 @@
<b-row>
<b-col :cols=12 :md=3>
<b-button :variant="isCorrespondingAuthor ? 'dark' : 'outline-dark'" @click="toggle(PERSON_TYPE_CORRESPONDING_AUTHOR)" class="w-100 person-type-button d-flex flex-column align-items-center">
<h2 :style="{ color: storeTraitColors[0] }"><PersonTypeIcon :personType="PERSON_TYPE_CORRESPONDING_AUTHOR" /></h2> <span>{{ $t('personTypeCorrespondingAuthor') }}</span>
<h2 :style="{ color: storeTraitColors[0 % storeTraitColors.length] }"><PersonTypeIcon :personType="PERSON_TYPE_CORRESPONDING_AUTHOR" /></h2> <span>{{ $t('personTypeCorrespondingAuthor') }}</span>
</b-button>
</b-col>
<b-col :cols=12 :md=3>
<b-button :variant="isDataCollector ? 'dark' : 'outline-dark'" @click="toggle(PERSON_TYPE_DATA_COLLECTOR)" class="w-100 person-type-button d-flex flex-column align-items-center">
<h2 :style="{ color: storeTraitColors[1] }"><PersonTypeIcon :personType="PERSON_TYPE_DATA_COLLECTOR" /></h2> <span>{{ $t('personTypeDataCollector') }}</span>
<h2 :style="{ color: storeTraitColors[1 % storeTraitColors.length] }"><PersonTypeIcon :personType="PERSON_TYPE_DATA_COLLECTOR" /></h2> <span>{{ $t('personTypeDataCollector') }}</span>
</b-button>
</b-col>
<b-col :cols=12 :md=3>
<b-button :variant="isQualityChecker ? 'dark' : 'outline-dark'" @click="toggle(PERSON_TYPE_QUALITY_CHECKER)" class="w-100 person-type-button d-flex flex-column align-items-center">
<h2 :style="{ color: storeTraitColors[2] }"><PersonTypeIcon :personType="PERSON_TYPE_QUALITY_CHECKER" /></h2> <span>{{ $t('personTypeQualityChecker') }}</span>
<h2 :style="{ color: storeTraitColors[2 % storeTraitColors.length] }"><PersonTypeIcon :personType="PERSON_TYPE_QUALITY_CHECKER" /></h2> <span>{{ $t('personTypeQualityChecker') }}</span>
</b-button>
</b-col>
<b-col :cols=12 :md=3>
<b-button :variant="isSubmitter ? 'dark' : 'outline-dark'" @click="toggle(PERSON_TYPE_DATA_SUBMITTER)" class="w-100 person-type-button d-flex flex-column align-items-center">
<h2 :style="{ color: storeTraitColors[3] }"><PersonTypeIcon :personType="PERSON_TYPE_DATA_SUBMITTER" /></h2> <span>{{ $t('personTypeDataSubmitter') }}</span>
<h2 :style="{ color: storeTraitColors[3 % storeTraitColors.length] }"><PersonTypeIcon :personType="PERSON_TYPE_DATA_SUBMITTER" /></h2> <span>{{ $t('personTypeDataSubmitter') }}</span>
</b-button>
</b-col>
</b-row>
Expand Down
8 changes: 4 additions & 4 deletions src/components/modals/TrialPersonSelectModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ export default {
]),
personStyle: function () {
const result = {}
result[PERSON_TYPE_CORRESPONDING_AUTHOR] = this.storeTraitColors[0]
result[PERSON_TYPE_DATA_COLLECTOR] = this.storeTraitColors[1]
result[PERSON_TYPE_QUALITY_CHECKER] = this.storeTraitColors[2]
result[PERSON_TYPE_DATA_SUBMITTER] = this.storeTraitColors[3]
result[PERSON_TYPE_CORRESPONDING_AUTHOR] = this.storeTraitColors[0 % this.storeTraitColors.length]
result[PERSON_TYPE_DATA_COLLECTOR] = this.storeTraitColors[1 % this.storeTraitColors.length]
result[PERSON_TYPE_QUALITY_CHECKER] = this.storeTraitColors[2 % this.storeTraitColors.length]
result[PERSON_TYPE_DATA_SUBMITTER] = this.storeTraitColors[3 % this.storeTraitColors.length]
return result
}
Expand Down
5 changes: 5 additions & 0 deletions src/plugins/changelog/de_DE.json
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,11 @@
"type": "new",
"title": "Datensatatistiken",
"text": "Eine Datenstatistk-Übersichtsseite wurde zu GridScore hinzugefügt welche verschiedene Ansichten auf die Daten erlaubt, z.B. eine Kalendarheatmap welche arbeitsreiche Tage hervorhebt sowie die Fläche die durch Datensammlung abgedeckt wurde und Vieles mehr."
},
{
"type": "new",
"title": "Farbpaletten",
"text": "Eine Vorauswahl von vordefinierten Farbpaletten wurde hinzugefügt. Diese beinhalten die Standard GridScore Palette sowie gängige Farbpaletten."
}
]
}
Expand Down
5 changes: 5 additions & 0 deletions src/plugins/changelog/en_GB.json
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,11 @@
"type": "new",
"title": "Data statistics",
"text": "An overview trial statistics page has been added to GridScore that shows various views onto the data like a calendar heatmap showing busy data collection days as well as stats on the size of area covered by data collection and many others."
},
{
"type": "new",
"title": "Color palettes",
"text": "Added a pre-selection of color palettes to choose from. These include the default GridScore palette as well as other well-known color palettes."
}
]
}
Expand Down
12 changes: 11 additions & 1 deletion src/plugins/color.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,19 @@ const shadeColor = (hex, percent) => {
return rgbToHex({ r, g, b })
}

const categoricalColors = {
GridScoreDefault: ['#910080', '#ff7c00', '#5ec418', '#00a0f1', '#c5e000', '#ff007a', '#222183', '#c83831', '#fff600'],
CBQuantPair12: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f', '#ff7f00', '#cab2d6', '#6a3d9a', '#ffff99', '#b15928'],
CBQuantSet19: ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00', '#ffff33', '#a65628', '#f781bf', '#999999'],
CBQuantDark28: ['#1b9e77', '#d95f02', '#7570b3', '#e7298a', '#66a61e', '#e6ab02', '#a6761d', '#666666'],
OkabeIto: ['#E69F00', '#56B4E9', '#009E73', '#F5C710', '#0072B2', '#D55E00', '#CC79A7', '#999999', '#000000'],
D3schemeCategory10: ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf']
}

export {
getHighContrastTextColor,
shadeColor,
hexToRgb,
rgbToHex
rgbToHex,
categoricalColors
}
3 changes: 3 additions & 0 deletions src/plugins/i18n/de_DE.json
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,9 @@
"formDescriptionPersonRole": "Eine Rolle die die Hauptfunktion dieser Person angibt. Es ist zu beachten, dass diese Rolle keinerlei Einfluss auf die Funktionsweise von GridScore hat.",
"formLabelTrialSetupTrialPeople": "Involvierte Personen",
"formDescriptionTrialSetupTrialPeople": "Optional können Personen definiert werden die am Versuch beteiligt sind.",
"formLabelSettingsTraitColorPreset": "Farbvorauswahl auswählen",
"formDescriptionSettingsTraitColorPreset": "Wähle eine dieser gängigen Farbvorauswahlen.",
"dropdownSettingsTraitColorPreset": "Farbvorauswahlen",
"menuHome": "Home",
"menuDataEntry": "Dateneingabe",
"menuDataExport": "Exportieren",
Expand Down
3 changes: 3 additions & 0 deletions src/plugins/i18n/en_GB.json
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,9 @@
"formDescriptionPersonRole": "A role that determines the main purpose of this person. Please note that these do not affect the way GridScore behaves.",
"formLabelTrialSetupTrialPeople": "People involved",
"formDescriptionTrialSetupTrialPeople": "Optionally, define everyone who is involved in this trial.",
"formLabelSettingsTraitColorPreset": "Pick color preset",
"formDescriptionSettingsTraitColorPreset": "Choose one of these commonly used color presets.",
"dropdownSettingsTraitColorPreset": "Color presets",
"genericDisabled": "Disabled",
"genericEnabled": "Enabled",
"genericYes": "Yes",
Expand Down
3 changes: 0 additions & 3 deletions src/plugins/misc.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import store from '@/store'
import { saveAs } from 'file-saver'
import { DISPLAY_ORDER_LEFT_TO_RIGHT, DISPLAY_ORDER_TOP_TO_BOTTOM } from './constants'

const categoryColors = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf']

const DIVISIONS = [
{ amount: 60, name: 'seconds' },
{ amount: 60, name: 'minutes' },
Expand Down Expand Up @@ -531,7 +529,6 @@ export {
isOffline,
checkDataMatchesTraitType,
isValidDateString,
categoryColors,
getNumberWithSuffix,
truncateAfterWords,
formatTimeAgo
Expand Down
16 changes: 8 additions & 8 deletions src/views/DataStatistics.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,52 +26,52 @@
<b-row class="my-3 text-center" v-if="stats[trial.localId]">
<b-col cols=6 md=4 lg=3 xl=2 offset-xl=2 class="mb-3">
<b-card class="h-100 bg-dark text-light">
<h3 class="mb-0" :style="{ color: storeTraitColors[0] }"><BIconUiChecksGrid /></h3>
<h3 class="mb-0" :style="{ color: storeTraitColors[0 % storeTraitColors.length] }"><BIconUiChecksGrid /></h3>
<span>{{ $t('widgetTrialDataStatsPlots', { count: (stats[trial.localId].plots || 0).toLocaleString() }) }}</span>
</b-card>
</b-col>
<b-col cols=6 md=4 lg=3 xl=2 class="mb-3">
<b-card class="h-100 bg-dark text-light">
<h3 class="mb-0" :style="{ color: storeTraitColors[1] }"><BIconTags /></h3>
<h3 class="mb-0" :style="{ color: storeTraitColors[1 % storeTraitColors.length] }"><BIconTags /></h3>
<span>{{ $t('widgetTrialDataStatsTraits', { count: (stats[trial.localId].traits || 0).toLocaleString() }) }}</span>
</b-card>
</b-col>
<b-col cols=6 md=4 lg=3 xl=2 class="mb-3">
<b-card class="h-100 bg-dark text-light">
<h3 class="mb-0" :style="{ color: storeTraitColors[2] }"><BIconChatLeftText /></h3>
<h3 class="mb-0" :style="{ color: storeTraitColors[2 % storeTraitColors.length] }"><BIconChatLeftText /></h3>
<span>{{ $t('widgetTrialDataStatsComments', { count: (stats[trial.localId].comments || 0).toLocaleString() }) }}</span>
</b-card>
</b-col>
<b-col cols=6 md=4 lg=3 xl=2 class="mb-3">
<b-card class="h-100 bg-dark text-light">
<h3 class="mb-0" :style="{ color: storeTraitColors[3] }"><BIconFlag /></h3>
<h3 class="mb-0" :style="{ color: storeTraitColors[3 % storeTraitColors.length] }"><BIconFlag /></h3>
<span>{{ $t('widgetTrialDataStatsEvents', { count: (stats[trial.localId].events || 0).toLocaleString() }) }}</span>
</b-card>
</b-col>
<b-col cols=6 md=4 lg=3 xl=2 offset-xl=2 class="mb-3">
<b-card class="h-100 bg-dark text-light">
<h3 class="mb-0" :style="{ color: storeTraitColors[4] }"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" class="bi bi-123" viewBox="0 0 16 16">
<h3 class="mb-0" :style="{ color: storeTraitColors[4 % storeTraitColors.length] }"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" class="bi bi-123" viewBox="0 0 16 16">
<path d="M2.873 11.297V4.142H1.699L0 5.379v1.137l1.64-1.18h.06v5.961zm3.213-5.09v-.063c0-.618.44-1.169 1.196-1.169.676 0 1.174.44 1.174 1.106 0 .624-.42 1.101-.807 1.526L4.99 10.553v.744h4.78v-.99H6.643v-.069L8.41 8.252c.65-.724 1.237-1.332 1.237-2.27C9.646 4.849 8.723 4 7.308 4c-1.573 0-2.36 1.064-2.36 2.15v.057zm6.559 1.883h.786c.823 0 1.374.481 1.379 1.179.01.707-.55 1.216-1.421 1.21-.77-.005-1.326-.419-1.379-.953h-1.095c.042 1.053.938 1.918 2.464 1.918 1.478 0 2.642-.839 2.62-2.144-.02-1.143-.922-1.651-1.551-1.714v-.063c.535-.09 1.347-.66 1.326-1.678-.026-1.053-.933-1.855-2.359-1.845-1.5.005-2.317.88-2.348 1.898h1.116c.032-.498.498-.944 1.206-.944.703 0 1.206.435 1.206 1.07.005.64-.504 1.106-1.2 1.106h-.75z"/>
</svg></h3>
<span>{{ $t('widgetTrialDataStatsMeasurements', { count: (stats[trial.localId].measurements || 0).toLocaleString() }) }}</span>
</b-card>
</b-col>
<b-col cols=6 md=4 lg=3 xl=2 class="mb-3">
<b-card class="h-100 bg-dark text-light">
<h3 class="mb-0" :style="{ color: storeTraitColors[5] }"><BIconBoundingBoxCircles /></h3>
<h3 class="mb-0" :style="{ color: storeTraitColors[5 % storeTraitColors.length] }"><BIconBoundingBoxCircles /></h3>
<span v-if="stats[trial.localId].area">{{ $t('widgetTrialDataStatsArea', { area: (areaUnits[areaUnit].convert(stats[trial.localId].area) || 0).toLocaleString(), unit: areaUnits[areaUnit].unit }) }}</span>
<span v-else>{{ $t('widgetTrialDataStatsAreaUnknown') }}</span>
</b-card>
</b-col>
<b-col cols=6 md=4 lg=3 xl=2 class="mb-3">
<b-card class="h-100 bg-dark text-light">
<h3 class="mb-0" :style="{ color: storeTraitColors[7] }"><BIconCalendarRangeFill /></h3>
<h3 class="mb-0" :style="{ color: storeTraitColors[7 % storeTraitColors.length] }"><BIconCalendarRangeFill /></h3>
<span>{{ $t('widgetTrialDataStatsDayRange', { count: (stats[trial.localId].dayRange || 0).toLocaleString() }) }}</span>
</b-card>
</b-col>
<b-col cols=6 md=4 lg=3 xl=2 class="mb-3">
<b-card class="h-100 bg-dark text-light">
<h3 class="mb-0" :style="{ color: storeTraitColors[8] }"><BIconCalendarDateFill /></h3>
<h3 class="mb-0" :style="{ color: storeTraitColors[8 % storeTraitColors.length] }"><BIconCalendarDateFill /></h3>
<span>{{ $t('widgetTrialDataStatsActiveDays', { count: (stats[trial.localId].activeDays || 0).toLocaleString() }) }}</span>
</b-card>
</b-col>
Expand Down
33 changes: 31 additions & 2 deletions src/views/SettingsView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,20 @@
</b-input-group>
</b-form-group>

<b-form-group :label="$t('formLabelSettingsTraitColorPreset')" label-for="preset-color" :description="$t('formDescriptionSettingsTraitColorPreset')" class="settings-colors">
<b-input-group>
<b-dropdown id="preset-color" :text="$t('dropdownSettingsTraitColorPreset')">
<b-dropdown-group :header="colorKey" v-for="colorKey in Object.keys(categoricalColors)" :key="`color-preset-${colorKey}`">
<b-dropdown-item @click="selectColorPreset(categoricalColors[colorKey])">
<div class="d-flex flex-row gradient">
<div v-for="color in categoricalColors[colorKey]" :key="`color-preset-${colorKey}-${color}`" :style="{ background: color }" />
</div>
</b-dropdown-item>
</b-dropdown-group>
</b-dropdown>
</b-input-group>
</b-form-group>

<b-form-group :label="$t('formLabelSettingsHighlightControls')" :description="$t('formDescriptionSettingsHighlightControls')" label-for="highlightControls">
<b-form-checkbox id="highlightControls" v-model="highlightControls" switch>
{{ highlightControls ? $t('genericYes') : $t('genericNo') }}
Expand Down Expand Up @@ -175,6 +189,7 @@ import { BIconHandIndex, BIconX, BIconShare, BIconArrowsMove, BIconPlus, BIconAr
import { NAVIGATION_MODE_JUMP, NAVIGATION_MODE_DRAG, CANVAS_DENSITY_LOW, CANVAS_DENSITY_MEDIUM, CANVAS_DENSITY_HIGH, CANVAS_SHAPE_CIRCLE, CANVAS_SHAPE_SQUARE, CANVAS_SIZE_SMALL, CANVAS_SIZE_MEDIUM, CANVAS_SIZE_LARGE } from '@/plugins/constants'
import SettingsShareModal from '@/components/modals/SettingsShareModal'
import draggable from 'vuedraggable'
import { categoricalColors } from '@/plugins/color'
const emitter = require('tiny-emitter/instance')
Expand Down Expand Up @@ -223,7 +238,8 @@ export default {
navigationMode: null,
traitColors: [],
newColor: '#000000',
showFullTraitDescription: true
showFullTraitDescription: true,
categoricalColors
}
},
computed: {
Expand Down Expand Up @@ -344,6 +360,9 @@ export default {
}
},
methods: {
selectColorPreset: function (colors) {
this.traitColors = colors.concat()
},
addColor: function () {
this.traitColors.push(this.newColor)
this.newColor = '#000000'
Expand All @@ -354,7 +373,7 @@ export default {
}
},
resetColors: function () {
this.traitColors = ['#910080', '#ff7c00', '#5ec418', '#00a0f1', '#c5e000', '#ff007a', '#222183', '#c83831', '#fff600']
this.traitColors = categoricalColors.GridScoreDefault
},
reset: function () {
this.locale = this.storeLocale
Expand Down Expand Up @@ -399,3 +418,13 @@ export default {
cursor: move;
}
</style>

<style scoped>
.gradient {
min-width: 250px;
height: 30px;
}
.gradient > div {
flex-grow: 1;
}
</style>
8 changes: 4 additions & 4 deletions src/views/TrialSetupView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -331,10 +331,10 @@ export default {
]),
personStyle: function () {
const result = {}
result[PERSON_TYPE_CORRESPONDING_AUTHOR] = this.storeTraitColors[0]
result[PERSON_TYPE_DATA_COLLECTOR] = this.storeTraitColors[1]
result[PERSON_TYPE_QUALITY_CHECKER] = this.storeTraitColors[2]
result[PERSON_TYPE_DATA_SUBMITTER] = this.storeTraitColors[3]
result[PERSON_TYPE_CORRESPONDING_AUTHOR] = this.storeTraitColors[0 % this.storeTraitColors.length]
result[PERSON_TYPE_DATA_COLLECTOR] = this.storeTraitColors[1 % this.storeTraitColors.length]
result[PERSON_TYPE_QUALITY_CHECKER] = this.storeTraitColors[2 % this.storeTraitColors.length]
result[PERSON_TYPE_DATA_SUBMITTER] = this.storeTraitColors[3 % this.storeTraitColors.length]
return result
},
Expand Down

0 comments on commit 2a7f298

Please sign in to comment.