diff --git a/src/ifctester/ifctester/facet.py b/src/ifctester/ifctester/facet.py index 658a109f13..bec92041f9 100644 --- a/src/ifctester/ifctester/facet.py +++ b/src/ifctester/ifctester/facet.py @@ -77,13 +77,16 @@ class Facet: templates = self.requirement_templates for template in templates: + total_variables = len(template) - len(template.replace("{", "")) + total_replacements = 0 for key in self.parameters: key = key.replace("@", "") value = getattr(self, key) key_variable = "{" + key + "}" if value is not None and key_variable in template: template = template.replace(key_variable, str(value)) - if "{" not in template: + total_replacements += 1 + if total_replacements == total_variables: return template def to_ids_value(self, parameter): @@ -574,7 +577,7 @@ class Restriction: def __str__(self): if self.type == "enumeration": - msg = "one of '%s'" % "' or '".join(self.options) + return "one of '%s'" % "' or '".join(self.options) elif self.type == "bounds": bounds = { "minInclusive": "larger or equal ", @@ -582,15 +585,14 @@ class Restriction: "minExclusive": "larger than ", "maxExclusive": "smaller than ", } - msg = "of value %s" % ", and ".join([bounds[x] + str(self.options[x]) for x in self.options]) + return "of value %s" % ", and ".join([bounds[x] + str(self.options[x]) for x in self.options]) elif self.type == "length": - msg = "with %s letters" % " and ".join(self.options) + return "%s letters long" % " and ".join(self.options) elif self.type == "pattern": - msg = "with pattern '%s'" % self.options + return "the pattern '%s'" % self.options # TODO add fractionDigits # TODO add totalDigits # TODO add whiteSpace - return msg class Result: diff --git a/src/ifctester/webapp/www/app.js b/src/ifctester/webapp/www/app.js new file mode 100644 index 0000000000..34f063706f --- /dev/null +++ b/src/ifctester/webapp/www/app.js @@ -0,0 +1,869 @@ +"use strict"; + +feather.replace() + +var ns = 'http://standards.buildingsmart.org/IDS'; +var xs = 'http://www.w3.org/2001/XMLSchema'; + +class IDSContainer extends HTMLElement { + connectedCallback() { + this.ids = null; + this.containerId = crypto.randomUUID(); + } +} + +class IDSInfo extends HTMLElement { + load(idsElement) { + this.idsElement = idsElement; + var idsInfoElements = this.getElementsByTagName('ids-info-element'); + for (var i=0; i c.toUpperCase()); + } + + load(idsParentElement, idsElement) { + this.idsElement = idsElement; + this.idsParentElement = idsParentElement; + if (idsElement) { + this.textContent = idsElement.textContent; + } + this.idsElement ? this.classList.remove('null') : this.classList.add('null'); + this.validate() ? this.classList.remove('error') : this.classList.add('error'); + } + + input(e) { + if ( ! this.idsElement && this.textContent) { + this.add(); + } + this.idsElement ? this.idsElement.textContent = this.textContent : null; + this.idsElement ? this.classList.remove('null') : this.classList.add('null'); + this.validate() ? this.classList.remove('error') : this.classList.add('error'); + } + + blur(e) { + if (this.idsElement && ( ! this.textContent)) { + this.remove(); + } + if ( ! this.textContent) { + this.textContent = this.defaultValue; + } + this.idsElement ? this.classList.remove('null') : this.classList.add('null'); + this.validate() ? this.classList.remove('error') : this.classList.add('error'); + } + + validate() { + if (this.attributes['name'].value == 'author') { + return this.textContent.match(new RegExp('[^@]+@[^\.]+\..+')) != null; + } else if (this.attributes['name'].value == 'date') { + return this.textContent.match(new RegExp('[0-9]{4}-[0-9]{2}-[0-9]{2}')) != null; + } + return true; + } + + add() { + var container = this.closest('ids-container'); + this.idsElement = container.ids.createElementNS(ns, this.attributes["name"].value); + this.idsElement.textContent = this.textContent; + this.idsParentElement.appendChild(this.idsElement); + } + + remove() { + this.idsParentElement.removeChild(this.idsElement); + this.idsElement = null; + } +} + +class IDSSpecRemove extends HTMLElement { + connectedCallback() { + this.addEventListener('click', this.click); + } + + click(e) { + var specs = this.closest('ids-specs'); + var spec = this.closest('ids-spec'); + specs.idsElement.removeChild(spec.idsElement); + specs.idsElement.dispatchEvent(new Event('ids-spec-remove')); + } +} + +class IDSSpecMove extends HTMLElement { + connectedCallback() { + this.direction = this.attributes['direction'].value; + this.addEventListener('click', this.click); + } + + load(idsElement) { + var self = this; + this.idsElement = idsElement; + this.render(); + } + + render() { + var index = Array.prototype.indexOf.call(this.idsElement.parentElement.children, this.idsElement); + if (index == 0 && this.direction == 'up') { + this.classList.add('hidden'); + } else if (index == this.idsElement.parentElement.children.length - 1 && this.direction == 'down') { + this.classList.add('hidden'); + } else { + this.classList.remove('hidden'); + } + } + + click(e) { + if (this.direction == "up") { + this.idsElement.parentElement.insertBefore(this.idsElement, this.idsElement.previousElementSibling); + } else if (this.direction == "down") { + var nextNextSibling = this.idsElement.nextElementSibling.nextElementSibling; + this.idsElement.parentElement.insertBefore(this.idsElement, nextNextSibling); + } + this.idsElement.parentElement.dispatchEvent(new Event('ids-spec-move')); + } +} + +class IDSSpecAdd extends HTMLElement { + connectedCallback() { + this.addEventListener('click', this.click); + } + + click(e) { + var specs = this.closest('ids-specs'); + var spec = this.closest('ids-spec'); + + var container = this.closest('ids-container'); + var newSpec = container.ids.createElementNS(ns, "specification"); + var newApplicability = container.ids.createElementNS(ns, "applicability"); + var newRequirements = container.ids.createElementNS(ns, "requirements"); + + specs.idsElement.insertBefore(newSpec, spec.idsElement.nextElementSibling); + newSpec.appendChild(newApplicability); + newSpec.appendChild(newRequirements); + specs.idsElement.dispatchEvent(new Event('ids-spec-add')); + } +} + +class IDSSpecHandle extends HTMLElement { + connectedCallback() { + this.addEventListener('dragstart', this.dragstart); + this.addEventListener('dragend', this.dragend); + } + + dragstart(e) { + var snippet = this.getElementsByClassName('snippet')[0]; + snippet.style.left = e.clientX + 'px'; + snippet.style.top = e.clientY + 'px'; + var dropzones = document.getElementsByTagName('ids-spec'); + for (var i=0; i'; + this.params.push(value.param); + } + var predefinedTypes = this.idsElement.getElementsByTagNameNS(ns, 'predefinedType'); + if (predefinedTypes.length) { + value = this.getIdsValue(predefinedTypes[0]); + if (value.type == 'simpleValue') { + parameters.type = '' + value.content + ''; + this.params.push(value.param); + } else if (value.type == 'enumeration') { + parameters.typeEnumeration = '' + value.content + ''; + this.params.push(value.param); + } + } + + this.innerHTML = this.renderTemplate(templates, parameters); + } + + loadAttribute() { + if (this.type == 'applicability') { + var templates = [ + 'Data where the {name} is provided', + 'Data where the {name} is {value}', + 'Data where the {name} follows the convention of {valuePattern}', + 'Data where the {name} is either {valueEnumeration}', + ]; + } else if (this.type == 'requirement') { + var templates = [ + 'The {name} shall be provided', + 'The {name} shall be {value}', + 'The {name} shall follow the convention of {valuePattern}', + 'The {name} shall be either {valueEnumeration}' + ]; + } + + var parameters = {}; + + var name = this.idsElement.getElementsByTagNameNS(ns, 'name')[0]; + var value = this.getIdsValue(name); + if (value.type == 'simpleValue') { + parameters.name = '' + this.sentence(value.content) + ''; + this.params.push(value.param); + } + var values = this.idsElement.getElementsByTagNameNS(ns, 'value'); + if (values.length) { + value = this.getIdsValue(values[0]); + if (value.type == 'simpleValue') { + parameters.value = '' + value.content + ''; + this.params.push(value.param); + } else if (value.type == 'pattern') { + parameters.valuePattern = '' + value.content + ''; + this.params.push(value.param); + } else if (value.type == 'enumeration') { + parameters.valueEnumeration = '' + value.content + ''; + this.params.push(value.param); + } + } + + this.innerHTML = this.renderTemplate(templates, parameters); + } + + loadClassification() { + if (this.type == 'applicability') { + var templates = [ + 'Data classified using {system}', + 'Data classified as {reference}', + 'Data classified following the convention of {referencePattern}', + 'Data having a {system} reference of {reference}', + 'Data having a {system} reference following the convention of {referencePattern}', + ]; + } else if (this.type == 'requirement') { + var templates = [ + 'Shall be classified using {system}', + 'Shall be classified as {reference}', + 'Shall be classified following the convention of {referencePattern}', + 'Shall have a {system} reference of {reference}', + 'Shall have a {system} reference following the convention of {referencePattern}', + ]; + } + + var parameters = {}; + + var value; + var systems = this.idsElement.getElementsByTagNameNS(ns, 'system'); + if (systems.length) { + value = this.getIdsValue(systems[0]); + if (value.type == 'simpleValue') { + parameters.system = '' + value.content + ''; + this.params.push(value.param); + } + } + var references = this.idsElement.getElementsByTagNameNS(ns, 'value'); + if (references.length) { + value = this.getIdsValue(references[0]); + if (value.type == 'simpleValue') { + parameters.reference = '' + value.content + ''; + this.params.push(value.param); + } else if (value.type == 'pattern') { + parameters.referencePattern = '' + value.content + ''; + this.params.push(value.param); + } + } + + this.innerHTML = this.renderTemplate(templates, parameters); + } + + loadProperty() { + if (this.type == 'applicability') { + var templates = [ + 'Elements with {name} data in the dataset {pset}', + 'Elements with {name} data of {value} in the dataset {pset}', + 'Elements with {name} data following the convention of {valuePattern} in the dataset {pset}', + 'Elements with {name} data with either {valueEnumeration} in the dataset {pset}', + ]; + } else if (this.type == 'requirement') { + var templates = [ + '{name} data shall be provided in the dataset {pset}', + '{name} data shall be {value} and in the dataset {pset}', + '{name} data shall follow the convention of {valuePattern} and in the dataset {pset}', + '{name} data shall be one of {valueEnumeration} and in the dataset {pset}', + ]; + } + + var parameters = {}; + + var name = this.idsElement.getElementsByTagNameNS(ns, 'name')[0]; + var value = this.getIdsValue(name); + if (value.type == 'simpleValue') { + parameters.name = '' + this.sentence(value.content) + ''; + this.params.push(value.param); + } + + var values = this.idsElement.getElementsByTagNameNS(ns, 'value'); + if (values.length) { + value = this.getIdsValue(values[0]); + if (value.type == 'simpleValue') { + parameters.value = '' + value.content + ''; + this.params.push(value.param); + } else if (value.type == 'pattern') { + parameters.valuePattern = '' + value.content + ''; + this.params.push(value.param); + } else if (value.type == 'enumeration') { + parameters.valueEnumeration = '' + value.content + ''; + this.params.push(value.param); + } + } + + var propertySet = this.idsElement.getElementsByTagNameNS(ns, 'propertySet')[0]; + value = this.getIdsValue(propertySet); + if (value.type == 'simpleValue') { + parameters.pset = '' + value.content + ''; + this.params.push(value.param); + } + + this.innerHTML = this.renderTemplate(templates, parameters); + } + + loadMaterial() { + if (this.type == 'applicability') { + var templates = [ + 'All data with a {value} material', + 'All data with a material of either {valueEnumeration}', + 'All data with a material', + ]; + } else if (this.type == 'requirement') { + var templates = [ + 'Shall shall have a material of {value}', + 'Shall have a material of either {valueEnumeration}', + 'Shall have a material', + ]; + } + + var parameters = {}; + + var value; + var values = this.idsElement.getElementsByTagNameNS(ns, 'value'); + if (values.length) { + value = this.getIdsValue(values[0]); + if (value.type == 'simpleValue') { + parameters.value = '' + value.content + ''; + this.params.push(value.param); + } else if (value.type == 'pattern') { + parameters.valuePattern = '' + value.content + ''; + this.params.push(value.param); + } else if (value.type == 'enumeration') { + parameters.valueEnumeration = '' + value.content + ''; + this.params.push(value.param); + } + } + + + this.innerHTML = this.renderTemplate(templates, parameters); + } + + loadPartOf() { + var templates = ['Must be part of a {entity}'] + + var parameters = {}; + + var content = this.capitalise(this.idsElement.attributes['entity'].value.toLowerCase().replace('ifc', '')) + parameters.entity = '' + content + ''; + this.params.push(this.idsElement); + + this.innerHTML = this.renderTemplate(templates, parameters); + } + + getIdsValue(element) { + var simpleValues = element.getElementsByTagNameNS(ns, 'simpleValue'); + if (simpleValues.length) { + return {type: 'simpleValue', param: simpleValues[0], content: simpleValues[0].textContent} + } + var restriction = element.getElementsByTagNameNS(xs, 'restriction')[0]; + var patterns = restriction.getElementsByTagNameNS(xs, 'pattern'); + if (patterns.length) { + return {type: 'pattern', param: patterns[0], content: patterns[0].attributes['value'].value} + } + var enumerations = restriction.getElementsByTagNameNS(xs, 'enumeration'); + if (enumerations.length) { + var values = []; + for (var i=0; i c.toUpperCase()); + } + + sentence(text) { + // E.g. ElevationOfSSLRelative --> Elevation Of S S L Relative + var words = text.match(/([A-Z]?[^A-Z]*)/g).slice(0,-1); + var mergedWords = []; + var mergedWord = ''; + for (var i=0; i Elevation Of SSL Relative + return mergedWords.join(' '); + } +} + +class IDSParam extends HTMLElement { + connectedCallback() { + this.contentEditable = true; + this.addEventListener('input', this.input); + this.filter = this.attributes['filter'] ? this.attributes['filter'].value : null; + } + + load(idsElement) { + this.idsElement = idsElement; + } + + input(e) { + if (this.filter == 'entityName') { + this.idsElement.textContent = 'IFC' + this.textContent.toUpperCase(); + } else if (this.filter == 'attributeName' || this.filter == 'propertyName') { + this.idsElement.textContent = this.textContent.replace(/\s+/g, ''); + } else { + this.idsElement.textContent = this.textContent; + } + } +} + +class IDSSpecs extends HTMLElement { + load(idsElement) { + var self = this; + this.idsElement = idsElement; + this.idsElement.addEventListener('ids-spec-remove', function() { self.render(); }); + this.idsElement.addEventListener('ids-spec-add', function() { self.render(); }); + this.idsElement.addEventListener('ids-spec-move', function() { self.render(); }); + this.render(); + } + + render() { + var template = this.getElementsByTagName('template')[0]; + + var children = []; + for (var i=0; i + + + + + + + + IfcTester + + + + + + + + + + + + + + + + + + +
+ IfcTester + New Spec + + Settings + Heeeelllp! + +
+ +
+
+ + +

My information requirements

+

+ + john@doe.com + + 1.0.0 + + date() + + Construction +

+

+ + An example suite of OpenBIM requirements for data quality audits + +

+

+ © Company Inc. +

+
+ + + +
+
+ +
+
+ + + + + + diff --git a/src/ifctester/webapp/www/normalize.css b/src/ifctester/webapp/www/normalize.css new file mode 100644 index 0000000000..192eb9ce43 --- /dev/null +++ b/src/ifctester/webapp/www/normalize.css @@ -0,0 +1,349 @@ +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ + +/* Document + ========================================================================== */ + +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in iOS. + */ + +html { + line-height: 1.15; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections + ========================================================================== */ + +/** + * Remove the margin in all browsers. + */ + +body { + margin: 0; +} + +/** + * Render the `main` element consistently in IE. + */ + +main { + display: block; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/* Grouping content + ========================================================================== */ + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ + +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +pre { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Remove the gray background on active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * 1. Remove the bottom border in Chrome 57- + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ + +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ + +b, +strong { + font-weight: bolder; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +code, +kbd, +samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/** + * Add the correct font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove the border on images inside links in IE 10. + */ + +img { + border-style: none; +} + +/* Forms + ========================================================================== */ + +/** + * 1. Change the font styles in all browsers. + * 2. Remove the margin in Firefox and Safari. + */ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ + +button, +input { /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ + +button, +select { /* 1 */ + text-transform: none; +} + +/** + * Correct the inability to style clickable types in iOS and Safari. + */ + +button, +[type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; +} + +/** + * Remove the inner border and padding in Firefox. + */ + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** + * Restore the focus styles unset by the previous rule. + */ + +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Correct the padding in Firefox. + */ + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ + +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} + +/** + * Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ + +progress { + vertical-align: baseline; +} + +/** + * Remove the default vertical scrollbar in IE 10+. + */ + +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10. + * 2. Remove the padding in IE 10. + */ + +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ + +[type="search"] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/** + * Remove the inner padding in Chrome and Safari on macOS. + */ + +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* Interactive + ========================================================================== */ + +/* + * Add the correct display in Edge, IE 10+, and Firefox. + */ + +details { + display: block; +} + +/* + * Add the correct display in all browsers. + */ + +summary { + display: list-item; +} + +/* Misc + ========================================================================== */ + +/** + * Add the correct display in IE 10+. + */ + +template { + display: none; +} + +/** + * Add the correct display in IE 10. + */ + +[hidden] { + display: none; +} diff --git a/src/ifctester/webapp/www/style.css b/src/ifctester/webapp/www/style.css new file mode 100644 index 0000000000..382aa1f57b --- /dev/null +++ b/src/ifctester/webapp/www/style.css @@ -0,0 +1,369 @@ +:root { + --green: #ccd5ae; + --red: #f08080; + --blue: #5aa9e6; + --light-blue: #7fc8f8; + --highlight: #faedcd; + --fg: #444; +} +html { + height: 100%; + scroll-behavior: smooth; +} +body { + height: calc(100% - 40px); + font-size: 0.8rem; + background-color: #FFF; + font-family: 'Libre Baskerville', serif; + border: 0px; + margin: 0px; + padding: 0px; + color: var(--fg); + transition: 0.3s ease-out; +} +header { + background-color: #333; + color: var(--blue); + font-family: 'Nova Mono', monospace; + height: 40px; + line-height: 40px; + padding-left: 10px; + padding-right: 10px; + text-transform: uppercase; +} +header a { + text-decoration: none; + margin-left: 10px; +} +header a:hover { + color: white; +} +header svg { + width: 16px; + height: 16px; + vertical-align: middle; + margin-top: -3px; + margin-right: 5px; +} +header span { + float: right; +} +* { + transition: 0.3s ease-out; +} +h3 { + font-family: 'Nova Mono', monospace; + text-transform: uppercase; + font-size: 0.8rem; + color: #ccc; +} +a { + color: #5aa9e6; +} +a:hover { + color: #7fc8f8; +} +.ids { + width: 700px; + height: calc(100%); + overflow: scroll; + float: left; + background-color: #f9f9f9; + padding-left: 20px; + padding-right: 20px; + box-shadow: rgba(100, 100, 111, 0.2) 0px 7px 29px 0px; +} +.ids-controls { + font-family: 'Nova Mono', monospace; + background-color: #f9f9f9; + background-color: #eee; + padding: 10px; + /*box-shadow: rgba(0, 0, 0, 0.12) 0px 1px 3px, rgba(0, 0, 0, 0.24) 0px 1px 2px;*/ +} +.ids-controls span { + float: right; +} +.ids-controls:hover a { + opacity: 1; + transition: 0.3s ease-out; +} +.ids-controls ids-loader a { + margin-left: 0px; +} +.ids-controls a { + margin-left: 10px; + font-size: 0.8rem; + /* + opacity: 0.4; + transition: 0.3s ease-in; + border-radius: 5px; + border: 1px solid var(--blue); + padding: 10px; + */ + text-decoration: none; + cursor: pointer; +} +.ids-controls a svg { + width: 16px; + height: 16px; + vertical-align: middle; + top: -2px; + position: relative; +} +.divider { + margin-top: -10px; + margin-bottom: 25px; + border-bottom: 1px dashed #ccc; + text-align: center; + color: #ccc; +} +.dragover { + background-color: var(--blue) !important; +} +.dropzone { + background-color: var(--highlight); +} +ids-spec .controls ids-facet-add { + position: absolute; + margin-left: -30px; + margin-top: -5px; +} +ids-spec .controls { + display: none; +} +ids-spec:hover .placeholder { + display: none; +} +ids-spec:hover .controls { + display: inline; +} +ids-spec:hover ids-spec-add:hover svg { + color: var(--blue); + cursor: pointer; +} +ids-spec:hover ids-spec-move:hover svg { + color: var(--fg); + cursor: pointer; +} +.divider svg { + display: inline-block; + position: relative; + top: 27px; + background-color: #f9f9f9; + padding: 10px; +} +ids-spec { + display: block; + padding-left: 30px; + overflow: hidden; +} +ids-spec h2 a, .spec h2 a { + display: none; +} +ids-spec:hover h2 a, .spec:hover h2 a { + display: inline-block; + position: absolute; + margin-left: -30px; + margin-top: -3px; + cursor: pointer; +} +ids-spec .draggable { + display: none; +} +ids-spec ids-spec-remove { + display: none; +} +ids-spec:hover ids-spec-remove { + display: inline-block; + position: absolute; + margin-left: -30px; + margin-top: 57px; + cursor: pointer; + color: #aaa; +} +ids-spec:hover ids-spec-remove:hover { + color: var(--red); +} +ids-spec:hover .draggable:hover { + color: var(--fg); +} +ids-spec:hover .draggable { + display: inline-block; + position: absolute; + margin-left: -30px; + margin-top: 27px; + cursor: grab; + color: #aaa; +} +ids-spec ids-spec-handle .snippet { + position: fixed; + z-index: 1; + background-color: var(--blue); + padding: 5px; + color: #f9f9f9; + text-transform: uppercase; + font-size: 0.7rem; + font-family: 'Nova Mono', monospace; + top: 0px; + left: 0px; +} +.spec-contents { + margin-left: 30px; + max-height: 9999px; +} +.spec-description { + font-weight: bold; +} +.facet .facet-controls { + display: none; +} +.facet:hover .facet-controls { + display: inline; +} +.facet:hover .facet-controls ids-facet-remove { + color: #aaa; + position: absolute; + margin-top: -3px; + margin-left: -30px; + cursor: pointer; +} +.facet:hover .facet-controls ids-facet-remove:hover svg { + color: var(--red); +} +.facet { + padding-left: 30px; + margin-bottom: 10px; +} +.facet .requirement-instructions.null { + display: none; +} +.facet:hover .requirement-instructions.null { + display: block; + z-index: 99; + position: absolute; + width: 300px; + padding: 10px; + border-radius: 5px; + background-color: #e0e0e0; + color: #aaa; + /*box-shadow: rgba(0, 0, 0, 0.12) 0px 1px 3px, rgba(0, 0, 0, 0.24) 0px 1px 2px;*/ + box-shadow: rgba(100, 100, 111, 0.2) 0px 7px 29px 0px; + margin-top: 2px; +} +.requirement-instructions { + display: block; + margin-left: 30px; + margin-top: 5px; + font-size: 0.8rem; +} +.pattern { + font-family: 'Nova Mono', monospace; + border-bottom: 1px dotted #555; + background-color: #faedcd; + cursor: help; + font-family: monospace; + text-overflow: ellipsis; + max-width: 250px; + white-space: nowrap; + overflow: hidden; + display: inline-block; + bottom: -5px; + position: relative; +} +.result-icon { + display: inline-block; + position: absolute; + margin-left: -30px; + margin-top: -2px; + cursor: help; +} +.result-icon.pass { + color: var(--green); +} +.result-icon.fail { + color: var(--red); +} +.result-icon:hover { + color: var(--blue); +} +.hidden { + display: none; +} +.error { + color: var(--red); + transition: 0.3s ease-out; +} +.null { + /*opacity: 0.4;*/ + color: #ccc; + transition: 0.3s ease-out; +} +.null:hover { + color: var(--fg) !important; +} +[contenteditable] { + outline: 0px solid transparent; +} +*[contentEditable="true"] { + /*box-shadow: rgba(100, 100, 111, 0.2) 0px 7px 29px 0px;*/ + border-radius: 5px; + cursor: pointer; +} +*[contentEditable="true"]:hover { + outline: 1px solid var(--blue); + outline-offset: 2px; + display: inline-block; + /*background-color: rgba(0, 0, 0, 0.1);*/ + background-color: #e0e0e0; +} +*[contentEditable="true"]:focus { + background-color: var(--light-blue); + outline: 0px; + padding: 5px; + margin: -5px; + display: inline-block; + cursor: text; +} +ids-info { + text-align: center; + margin-bottom: 20px; + display: block; +} +ids-info p { + font-size: 0.8rem; +} +ids-info svg { + width: 16px; + height: 16px; + vertical-align: middle; +} +ids-info-element[ids-tag="description"] { + font-style: italic; +} +ids-param { + font-style: italic; +} +ids-facet { + display: block; +} +nav { + position: relative; + float: left; + width: 200px; + /*background-color: #fafafa;*/ + overflow-x: hidden; /* Disable horizontal scroll */ + overflow-y: scroll; + height: 100%; + /* + -webkit-mask-image: linear-gradient(to bottom, black 80%, transparent 100%); + mask-image: linear-gradient(to bottom, black 80%, transparent 100%); + */ + /*box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;*/ + font-size: 0.7rem; +} +nav ids-spec { + padding-left: 0px; + border-bottom: 1px dashed #ccc; + padding: 15px; + display: block; +}