Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Items identified after release v3.0.0 #420

Merged
merged 26 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
8e46790
Don't show Genotype Table if handsOnTableLicenseKey is not defined
Don-Isdale Oct 24, 2024
e2af2e9
Don't show Feature Table if handsOnTableLicenseKey is not defined
Don-Isdale Oct 24, 2024
7ce4a58
Update Feature Search results triangles which span multiple blocks
Don-Isdale Oct 25, 2024
c739c7c
fix block matching of blast search results
Don-Isdale Oct 29, 2024
3738681
view transient blocks
Don-Isdale Oct 29, 2024
c9ab9bb
blast-results-view : solve scope / referenceBlock issue
Don-Isdale Oct 30, 2024
10e9030
blast-results-view : more fixes related to showing the required blast…
Don-Isdale Oct 31, 2024
47b5b9e
blast-results-view : update display of axis and features triangles an…
Don-Isdale Oct 31, 2024
3e9941a
fix request of feature counts
Don-Isdale Nov 1, 2024
1aea0c5
fix axis heading feature count being / undefined - re-enable initial …
Don-Isdale Nov 1, 2024
2ef1624
take popoverTarget out of layout flow so that it does not move the gr…
Don-Isdale Nov 1, 2024
684b5aa
update version to 3.0.1
Don-Isdale Nov 1, 2024
680b217
Genotype Table selected SNPs alt/ref : don't show the whole cell gree…
Don-Isdale Nov 6, 2024
efac7f4
retain selected SNPs when another dataset is added in Genotype Table
Don-Isdale Nov 9, 2024
c55b559
don't switch to dataset tab if Genotype Table is displayed
Don-Isdale Nov 11, 2024
61cd931
improve sampleFiltersCopy : check if a feature is in this block; all…
Don-Isdale Nov 11, 2024
6954890
exclude datasetId from Genotype Table column header height calculation
Don-Isdale Nov 11, 2024
83f6bda
after logout route to login instead of /undefined and 404
Don-Isdale Nov 14, 2024
221363b
restore the redirection to /mapview after login
Don-Isdale Nov 14, 2024
8e75232
data_templates : copy new worksheet types from xltx to ots
Don-Isdale Nov 15, 2024
a021759
handle and report to GUI when error in upload VCF worksheet
Don-Isdale Nov 17, 2024
4891a95
Add server trace of unhandled exception and promise rejection
Don-Isdale Nov 17, 2024
e36e5d7
update version 3.0.1 to 3.1.0
Don-Isdale Nov 18, 2024
9901ddb
Merge pull request #418 from plantinformatics/feature/postReleaseIssues
Don-Isdale Nov 18, 2024
9e4ed3d
handle some exceptions
Don-Isdale Nov 18, 2024
f8c4dec
Merge pull request #419 from plantinformatics/feature/postReleaseIssues
Don-Isdale Nov 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions frontend/app/components/draw/axis-ticks-selected.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ const dLog = console.debug;
const CompName = 'components/axis-ticks-selected';

/*----------------------------------------------------------------------------*/
/** @return true if feature's block is not viewed and its dataset
/** @return true if feature's block's dataset
* has tag transient.
*/
function featureIsTransient(f) {
let isTransient = ! f.get('blockId.isViewed');
if (isTransient) {
/** transient blocks are viewed, after c739c7cd. */
let isTransient;
{
let d = f.get('blockId.datasetId');
d = d.get('content') || d;
isTransient = d.hasTag('transient');
Expand All @@ -46,6 +47,13 @@ export default Component.extend(AxisEvents, {
selected : service('data/selected'),
controls : service(),

/** set up a component reference for use in the Web Inspector console */
develRefnSetup : on('init', function () {
// used in development only, in Web Inspector console.
if (window.PretzelFrontend) {
window.PretzelFrontend.axisTicksSelected = this;
}
}),

resized : function(widthChanged, heightChanged, useTransition) {
/* useTransition could be passed down to showTickLocations()
Expand Down Expand Up @@ -107,6 +115,7 @@ export default Component.extend(AxisEvents, {
'selected.shiftClickedFeatures.length',
'selected.labelledFeatures.length',
'selected.features.length',
'axis1d.blocks.length',
function () {
this.renderTicksThrottle();
}),
Expand Down
12 changes: 9 additions & 3 deletions frontend/app/components/matrix-view.js
Original file line number Diff line number Diff line change
Expand Up @@ -319,8 +319,12 @@ export default Component.extend({
return () => ! this.isDestroying && this.createOrUpdateTable();
}),

get useHandsOnTable() {
return !!config.handsOnTableLicenseKey;
},

createOrUpdateTable() {
if (! this.table) {
if (! this.table && this.useHandsOnTable) {
this.createTable();
}
if (! this.noData) {
Expand Down Expand Up @@ -630,7 +634,7 @@ export default Component.extend({
/** related : cornerClones */
topLeftDialog = $('#observational-table .ht_clone_top_left_corner .colHeader.cornerHeader')[0];
// dLog(fnName, topLeftDialog);
Ember_set(this, 'tableApi.topLeftDialog', topLeftDialog);
later(() => Ember_set(this, 'tableApi.topLeftDialog', topLeftDialog));
this.addComponentClass();
},

Expand Down Expand Up @@ -1680,7 +1684,9 @@ export default Component.extend({
let length_checker = $("#length_checker");
length_checker.css('font-weight', 'bold');
this.get('columnNames').forEach(function(col_name) {
let w = length_checker.text(col_name).width();
/** Just the sampleName is displayed, not datasetId. Similar in colHeaders, uses split(). */
const sampleName = columnName2SampleName(col_name);
let w = length_checker.text(sampleName).width();
if (w > longest) {
longest = w;
}
Expand Down
2 changes: 1 addition & 1 deletion frontend/app/components/panel/manage-explorer.js
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ export default ManageBase.extend({
this.set('blockFeatureOntologiesTreeEmbeddedKeyLength', keyLength); // perhaps rename both to keysLength.
return valueTree;
})
.catch(error => { dLog(fnName, error.responseJSON.error || error); return Promise.resolve({}); });
.catch(error => { dLog(fnName, error.responseJSON?.error || error); return Promise.resolve({}); });
return promise;
}),

Expand Down
2 changes: 2 additions & 0 deletions frontend/app/components/panel/manage-genotype.hbs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{{this.selectedSampleEffect}}
{{this.sampleFiltersCopyEffect}}
{{!-- this.gtBlockViewEffect --}}
{{will-destroy this.onWillDestroy}}

{{#if this.showInputDialog}}
Expand Down
197 changes: 183 additions & 14 deletions frontend/app/components/panel/manage-genotype.js
Original file line number Diff line number Diff line change
Expand Up @@ -805,18 +805,23 @@ export default class PanelManageGenotypeComponent extends Component {
abBlocks.forEach((abBlock, i) => {
const
block = abBlock.block,
selected = block[sampleFiltersSymbol][filterTypeName],
blocksTypeFilters = 'blocks' + toTitleCase(filterTypeName) + 'Filters';
/** selected is equal to one of :
* this.blocksFeatureFilters[i].sampleFilters.feature
* this.blocksHaplotypeFilters[i].sampleFilters.haplotype
*/
if (selected !== this[blocksTypeFilters][i].sampleFilters[filterTypeName]) {
dLog(fnName, abBlock, this[blocksTypeFilters][i], selected);
}
if (selected.length) {
selected.removeAt(0, selected.length);
sampleFilters = block[sampleFiltersSymbol];
if (sampleFilters) {
const
selected = sampleFilters[filterTypeName],
blocksTypeFilters = 'blocks' + toTitleCase(filterTypeName) + 'Filters';
/** selected is equal to one of :
* this.blocksFeatureFilters[i].sampleFilters.feature
* this.blocksHaplotypeFilters[i].sampleFilters.haplotype
*/
if (selected !== this[blocksTypeFilters][i].sampleFilters[filterTypeName]) {
dLog(fnName, abBlock, this[blocksTypeFilters][i], selected);
}
if (selected?.length) {
selected.removeAt(0, selected.length);
}
}

const referenceSamples = block[referenceSamplesSymbol];
if (referenceSamples) {
arrayClear(referenceSamples);
Expand All @@ -838,7 +843,140 @@ export default class PanelManageGenotypeComponent extends Component {
later(() => this.matrixView.table.render(), 2000);
}
}


//----------------------------------------------------------------------------
/** Retain or reset selected SNPs when another dataset is added in Genotype Table.
* retain and reset are alternatives, and are implemented by gtBlockViewEffect
* and sampleFiltersCopyEffect respectively.
*/

/** Retain previous value of .gtBlocks seen by gtBlockViewEffect to detect added blocks */
gtBlocksPrevious = null;
/** Side Effect : clear sampleFilters if a new VCF Genotype block is viewed.
*/
@computed('gtBlocks')
get gtBlockViewEffect() {
const
fnName = 'gtBlockViewEffect',
blocks = this.gtBlocks,
gtBlocksPrevious = this.gtBlocksPrevious,
newBlocks = gtBlocksPrevious ? blocks.filter(block => ! gtBlocksPrevious.includes(block)) : blocks,
added = newBlocks.length;
this.gtBlocksPrevious = blocks;
if (added) {
dLog(fnName, newBlocks.mapBy('brushName'), blocks.mapBy('brushName'), gtBlocksPrevious?.mapBy('brushName'));
/* The Clear button calls sampleFiltersClear() and haplotypeFiltersApply()
* sampleFiltersClear() clears the filters for .sampleFilterTypeName, so
* set that and call Clear again.
*/
this.sampleFiltersClear();
this.setSelectedSampleFilter('feature', /*i*/undefined);
this.sampleFiltersClear();
this.haplotypeFiltersApply();
}
}
/** Side Effect : copy sampleFilters of another block if a new block is viewed. */
@computed('gtBlocks')
get sampleFiltersCopyEffect() {
/** allow time for brushed features to be loaded.
* Later, we can update after additional features are loaded, and also
* sampleFiltersCopyType() is intended to map the selected features to the
* added block when called again subsequently.
*/
later(() => ! this.isDestroying && this.sampleFiltersCopy(), 3000);
}
/** If a new VCF block is viewed, and it does not have [sampleFiltersSymbol]
* copy this from another block.
* Copy each of the attributes, whose keys are sampleFilterKeys.
*/
sampleFiltersCopy() {
const fnName = 'sampleFiltersCopy';
this.sampleFilterKeys.forEach(sampleFilterTypeName => this.sampleFiltersCopyType(sampleFilterTypeName));
dLog(fnName, this.sampleFiltersCheck());

// update selectedSampleEffect
later(() => {
this.selectedSampleRefreshDisplay(/*sampleFilterTypeName*/undefined);
// Repeat - will work out the requirements display to be refreshed.
later(() => {
! this.isDestroying && this.selectedSampleRefreshDisplay(/*sampleFilterTypeName*/undefined);
}, 1000);
});
}
/** If a new VCF block is viewed, and it does not have [sampleFiltersSymbol]
* copy this from another block.
*
* This has been tested on the case where there is 1 block displayed with
* selected SNPs on the same referenceBlock as a block which is added / viewed.
* This handles what may be the most useful and common case, and suits a user
* story which is being documented, but will have to be
* re-thought in other contexts, e.g. if there are 2 blocks with
* [sampleFiltersSymbol] (currently chooses the first one), or if the selected
* SNPs are not in this block.
*/
sampleFiltersCopyType(sampleFilterTypeName) {
const fnName = 'sampleFiltersCopyType';
{
const
blocks = this.gtBlocks,
filters = Object.groupBy(blocks, block => {
const
sampleFilters = block[sampleFiltersSymbol],
sampleFilter = sampleFilters?.[sampleFilterTypeName],
/** for sampleFilterTypeName 'feature' check if a feature is in this block.
* If the features' blocks !== block, then we want to do, below:
* map from copyThis features to block.features ...
*/
ok = sampleFilter?.length &&
((sampleFilterTypeName !== 'feature') ||
sampleFilter.find(feature => contentOf(feature.get('blockId')) === block));
return !!ok;
}),
newBlocks = filters['false'],
haveFilters = filters['true'];
if (haveFilters && newBlocks) {
newBlocks.forEach(block => {
const
/** Only match SNPs on the same reference block.
* There could be multiple haveFilters on the same .referenceBlock;
* just using the first. */
copyThis = haveFilters?.find(b => b.referenceBlock === block.referenceBlock),
copyThisFilter = copyThis?.[sampleFiltersSymbol],
copy =
Object.entries(copyThisFilter).reduce((O, [k,v]) => {O[k] = v.slice(0); return O;}, {});
dLog(fnName, 'copyThisFilter', copyThisFilter, copyThis.brushName, copy);

/** map from copyThis features to block.features, matching SNP position, i.e. .value_0 */
copy.feature?.forEach((f, i) => {
const f2 = block.get('features').findBy('value_0', f.value_0);
dLog(fnName, i, f, f2);
if (f2) {
f2[matchRefSymbol] = f[matchRefSymbol];
copy.feature[i] = f2;
}
/* else could remove copy.features[i], or search again later after
* more features are loaded. Could use API to request those features. */
});
block[sampleFiltersSymbol] = copy;
dLog(fnName, block);
});
}
}
}
/** Refresh display to show result of sampleFiltersCopy().
*/
selectedSampleRefreshDisplay(sampleFilterTypeName) {
if (! sampleFilterTypeName) {
sampleFilterTypeName = this.args.userSettings.sampleFilterTypeName;
}
// There is probably some redundancy here which can be reduced.
this.sampleFiltersSet(sampleFilterTypeName);
this.datasetPositionFilterChangeCount++;
this.haplotypeFiltersApply();
/* referenceSamples are separate from sampleFilters - could have a
* separate dependency/count for sampleFilters. */
this.referenceSamplesCount++;
}

/** Use Ember_set() to signal update of tracked properties and trigger re-render. */
sampleFiltersSet(filterTypeName) {
Expand Down Expand Up @@ -1060,6 +1198,26 @@ export default class PanelManageGenotypeComponent extends Component {
dLog(fnName, filterTypeName, axisBrushes, blocksF);
return blocksF;
}
/** Surface the details of the selected SNPs, to check result of
* sampleFiltersCopyType().
* This is similar to blocksSampleFilters(), but has a different use.
*/
sampleFiltersCheck() {
const
blocks = this.gtBlocks,
sampleFilters = blocks.map(block => {
const
sf = block[sampleFiltersSymbol],
features = this.blockSampleFilters(block, 'feature'),
featuresDesc = features.map(feature => [
feature.get('blockId.brushName'),
feature.value_0,
feature[matchRefSymbol],
]);
return featuresDesc;
});
return sampleFilters;
}
/** @return array of blocks and the features selected on them for filtering samples.
*/
@computed('brushedOrViewedVCFBlocks')
Expand Down Expand Up @@ -1543,11 +1701,22 @@ export default class PanelManageGenotypeComponent extends Component {
*/
const lookupBlock = this.args.userSettings.lookupBlock;
if (lookupBlock !== undefined) {
this.axisBrushBlockIndex = blocks.findIndex((abb) => abb.block === lookupBlock);
let axisBrushBlockIndex = blocks.findIndex((abb) => abb.block === lookupBlock);
/** .axisBrushBlockIndex may be -1, when data block is un-viewed while brushed.
* In this case, if there is another viewed block on the same axis, choose that,
* else if there are viewed blocks, choose the first one, because
* .axisBrushBlockIndex === -1 leads to .lookupBlock undefined, which
* gets undefined block in vcfGenotypeSamples().
*/
if (axisBrushBlockIndex === -1) {
axisBrushBlockIndex = blocks.findIndex((abb) => abb.block.referenceBlock === lookupBlock.referenceBlock);
} else if (blocks.length) {
axisBrushBlockIndex = 0;
}
this.axisBrushBlockIndex = axisBrushBlockIndex;
if (this.axisBrushBlockIndex === undefined) {
this.args.userSettings.lookupBlock = undefined;
}
/** .axisBrushBlockIndex maybe -1, when data block is un-viewed while brushed. */
dLog(fnName, this.axisBrushBlockIndex, blocks[this.axisBrushBlockIndex]?.block.id, blocks, lookupBlock.id);
} else if ((this.axisBrushBlockIndex === undefined) || (this.axisBrushBlockIndex > blocks.length-1)) {
/* first value is selected. if only 1 value then select onchange action will not be called. */
Expand Down
Loading