modules/core/validation/models.js (70 lines of code) (raw):

import { Extent } from '@id-sdk/extent'; import { utilTotalExtent } from '../../util'; import { t } from '../../core/localizer'; export function validationIssue(attrs) { this.type = attrs.type; // required - name of rule that created the issue (e.g. 'missing_tag') this.subtype = attrs.subtype; // optional - category of the issue within the type (e.g. 'relation_type' under 'missing_tag') this.severity = attrs.severity; // required - 'warning' or 'error' this.message = attrs.message; // required - function returning localized string this.reference = attrs.reference; // optional - function(selection) to render reference information this.entityIds = attrs.entityIds; // optional - array of IDs of entities involved in the issue this.loc = attrs.loc; // optional - [lon, lat] to zoom in on to see the issue this.data = attrs.data; // optional - object containing extra data for the fixes this.dynamicFixes = attrs.dynamicFixes;// optional - function(context) returning fixes this.hash = attrs.hash; // optional - string to further differentiate the issue this.id = generateID.apply(this); // generated - see below this.key = generateKey.apply(this); // generated - see below (call after generating this.id) // this.autoFix = null; // generated - if autofix exists, will be set below this.autoArgs = attrs.autoArgs; // optional - if this issue can be autofixed, supply the autofix args at issue creation // A unique, deterministic string hash. // Issues with identical id values are considered identical. function generateID() { var parts = [this.type]; if (this.hash) { // subclasses can pass in their own differentiator parts.push(this.hash); } if (this.subtype) { parts.push(this.subtype); } // include the entities this issue is for // (sort them so the id is deterministic) if (this.entityIds) { var entityKeys = this.entityIds.slice().sort(); parts.push.apply(parts, entityKeys); } return parts.join(':'); } // An identifier suitable for use as the second argument to d3.selection#data(). // (i.e. this should change whenever the data needs to be refreshed) function generateKey() { return this.id + ':' + Date.now().toString(); // include time of creation } this.extent = function(resolver) { if (this.loc) { return new Extent(this.loc); } if (this.entityIds && this.entityIds.length) { return utilTotalExtent(this.entityIds, resolver); } return null; }; this.fixes = function(context) { var fixes = this.dynamicFixes ? this.dynamicFixes(context) : []; var issue = this; if (issue.severity === 'warning') { // allow ignoring any issue that's not an error fixes.push(new validationIssueFix({ title: t.html('issues.fix.ignore_issue.title'), icon: 'iD-icon-close', onClick: function() { context.validator().ignoreIssue(this.issue.id); } })); } fixes.forEach(function(fix) { // the id doesn't matter as long as it's unique to this issue/fix fix.id = fix.title; // add a reference to the issue for use in actions fix.issue = issue; // if (fix.autoArgs) { // issue.autoFix = fix; // } }); return fixes; }; } export function validationIssueFix(attrs) { this.title = attrs.title; // Required this.onClick = attrs.onClick; // Optional - the function to run to apply the fix this.disabledReason = attrs.disabledReason; // Optional - a string explaining why the fix is unavailable, if any this.icon = attrs.icon; // Optional - shows 'iD-icon-wrench' if not set this.entityIds = attrs.entityIds || []; // Optional - used for hover-higlighting. // this.autoArgs = attrs.autoArgs; // Optional - pass [actions, annotation] arglist if this fix can automatically run this.issue = null; // Generated link - added by validationIssue }