mirror of
				https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
				synced 2025-10-31 10:42:43 +00:00 
			
		
		
		
	Locking end-tag of structural attributes, ...
This commit is contained in:
		| @@ -7,6 +7,10 @@ | ||||
|   margin-top: 23px; | ||||
| } | ||||
|  | ||||
| #corpus-analysis-concordance-query-builder-input-field-placeholder { | ||||
|   color: #9E9E9E; | ||||
| } | ||||
|  | ||||
| .modal-content { | ||||
|   overflow-x: hidden; | ||||
| } | ||||
| @@ -109,10 +113,10 @@ | ||||
| } | ||||
|  | ||||
| [data-type="start-empty-entity"], [data-type="start-entity"], [data-type="end-entity"] { | ||||
|   background-color: #A6E22D; | ||||
|   background-color: #a6e22d; | ||||
| } | ||||
|  | ||||
| [data-type="start-text-annotation"]{ | ||||
| [data-type="text-annotation"]{ | ||||
|   background-color: #2FBBAB; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -33,7 +33,7 @@ class CorpusAnalysisConcordance { | ||||
|  | ||||
|   async submitForm(queryModeId) { | ||||
|     this.app.disableActionElements(); | ||||
|     let queryBuilderQuery = document.querySelector('#corpus-analysis-concordance-query-preview').innerHTML.trim(); | ||||
|     let queryBuilderQuery = Utils.unescape(document.querySelector('#corpus-analysis-concordance-query-preview').innerHTML.trim()); | ||||
|     let expertModeQuery = this.elements.expertModeForm.query.value.trim(); | ||||
|     let query = queryModeId === 'corpus-analysis-concordance-expert-mode-form' ? expertModeQuery : queryBuilderQuery; | ||||
|     let form = queryModeId === 'corpus-analysis-concordance-expert-mode-form' ? this.elements.expertModeForm : this.elements.queryBuilderForm; | ||||
|   | ||||
| @@ -7,26 +7,28 @@ class ConcordanceQueryBuilder { | ||||
|     this.tokenAttributeBuilderFunctions = new TokenAttributeBuilderFunctionsQueryBuilder(this.elements); | ||||
|     this.structuralAttributeBuilderFunctions = new StructuralAttributeBuilderFunctionsQueryBuilder(this.elements); | ||||
|  | ||||
|     // Eventlisteners for the incidence modifiers. There are two different types of incidence modifiers: token and character incidence modifiers. | ||||
|     document.querySelectorAll('.incidence-modifier-selection').forEach(button => { | ||||
|       if (button.parentNode.parentNode.id === 'corpus-analysis-concordance-token-incidence-modifiers-dropdown') { | ||||
|         button.addEventListener('click', () => { | ||||
|           this.generalFunctions.tokenIncidenceModifierHandler(button.dataset.token, button.innerHTML);}); | ||||
|       } else if (button.parentNode.parentNode.id === 'corpus-analysis-concordance-character-incidence-modifiers-dropdown') { | ||||
|         button.addEventListener('click', () => {this.tokenAttributeBuilderFunctions.characterIncidenceModifierHandler(button);}); | ||||
|       let dropdownId = button.parentNode.parentNode.id; | ||||
|       if (dropdownId === 'corpus-analysis-concordance-token-incidence-modifiers-dropdown') { | ||||
|         button.addEventListener('click', () => this.generalFunctions.tokenIncidenceModifierHandler(button.dataset.token, button.innerHTML)); | ||||
|       } else if (dropdownId === 'corpus-analysis-concordance-character-incidence-modifiers-dropdown') { | ||||
|         button.addEventListener('click', () => this.tokenAttributeBuilderFunctions.characterIncidenceModifierHandler(button)); | ||||
|       } | ||||
|     }); | ||||
|      | ||||
|     // Eventlisteners for the submit of n- and m-values of the incidence modifier modal for "exactly n" or "between n and m". | ||||
|     document.querySelectorAll('.n-m-submit-button').forEach(button => { | ||||
|       if (button.dataset.modalId === 'corpus-analysis-concordance-exactly-n-token-modal' || button.dataset.modalId === 'corpus-analysis-concordance-between-nm-token-modal') { | ||||
|         button.addEventListener('click', () => { | ||||
|           this.generalFunctions.tokenNMSubmitHandler(button.dataset.modalId); | ||||
|         }); | ||||
|       } else if (button.dataset.modalId === 'corpus-analysis-concordance-exactly-n-character-modal' || button.dataset.modalId === 'corpus-analysis-concordance-between-nm-character-modal') { | ||||
|         button.addEventListener('click', () => { | ||||
|           this.generalFunctions.characterNMSubmitHandler(button.dataset.modalId); | ||||
|         }); | ||||
|       let modalId = button.dataset.modalId; | ||||
|       if (modalId === 'corpus-analysis-concordance-exactly-n-token-modal' || modalId === 'corpus-analysis-concordance-between-nm-token-modal') { | ||||
|         button.addEventListener('click', () => this.generalFunctions.tokenNMSubmitHandler(modalId)); | ||||
|       } else if (modalId === 'corpus-analysis-concordance-exactly-n-character-modal' || modalId === 'corpus-analysis-concordance-between-nm-character-modal') { | ||||
|         button.addEventListener('click', () => this.generalFunctions.characterNMSubmitHandler(modalId)); | ||||
|       } | ||||
|     }); | ||||
|  | ||||
|     document.querySelector('#corpus-analysis-concordance-text-annotation-submit').addEventListener('click', () => this.structuralAttributeBuilderFunctions.textAnnotationSubmitHandler()); | ||||
|  | ||||
|     this.elements.positionalAttrModal = M.Modal.init( | ||||
|       document.querySelector('#corpus-analysis-concordance-positional-attr-modal'),  | ||||
|       { | ||||
|   | ||||
| @@ -9,6 +9,9 @@ class ElementReferencesQueryBuilder { | ||||
|     this.sentenceElement = document.querySelector('[data-structural-attr-modal-action-button="sentence"]'); | ||||
|     this.entityElement = document.querySelector('[data-structural-attr-modal-action-button="entity"]'); | ||||
|     this.textAnnotationElement = document.querySelector('[data-structural-attr-modal-action-button="text-annotation"]'); | ||||
|     this.englishEntTypeSelection = document.querySelector('#corpus-analysis-concordance-english-ent-type-selection'); | ||||
|     this.germanEntTypeSelection = document.querySelector('#corpus-analysis-concordance-german-ent-type-selection'); | ||||
|     this.textAnnotationSelection = document.querySelector('#corpus-analysis-concordance-text-annotation-options'); | ||||
|  | ||||
|     // Token Attribute Builder Elements | ||||
|     this.positionalAttrModal = M.Modal.getInstance(document.querySelector('#corpus-analysis-concordance-positional-attr-modal')); | ||||
|   | ||||
| @@ -10,36 +10,96 @@ class GeneralFunctionsQueryBuilder { | ||||
|   } | ||||
|  | ||||
|   updateChipList() { | ||||
|     this.elements.queryChipElements = this.elements.queryInputField.querySelectorAll('.chip'); | ||||
|     this.elements.queryChipElements = this.elements.queryInputField.querySelectorAll('.query-component'); | ||||
|   } | ||||
|  | ||||
|   queryChipFactory(dataType, prettyQueryText, queryText, index = null) { | ||||
|   removePlaceholder() { | ||||
|     let placeholder = this.elements.queryInputField.querySelector('#corpus-analysis-concordance-query-builder-input-field-placeholder');   | ||||
|     if (placeholder) { | ||||
|       this.elements.queryInputField.innerHTML = ''; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   addPlaceholder() { | ||||
|     let placeholder = Utils.HTMLToElement('<span id="corpus-analysis-concordance-query-builder-input-field-placeholder">Click on a button to add a query component</span>'); | ||||
|     this.elements.queryInputField.appendChild(placeholder); | ||||
|   } | ||||
|    | ||||
|   resetMaterializeSelection(selectionElements, value = "default") { | ||||
|     selectionElements.forEach(selectionElement => { | ||||
|       selectionElement.querySelector(`option[value=${value}]`).selected = true; | ||||
|       let instance = M.FormSelect.getInstance(selectionElement); | ||||
|       instance.destroy(); | ||||
|       M.FormSelect.init(selectionElement); | ||||
|     }) | ||||
|   } | ||||
|  | ||||
|  | ||||
|   queryChipFactory(dataType, prettyQueryText, queryText, index = null, isClosingTag = false) { | ||||
|     // Creates a new query chip element, adds Eventlisteners for selection, deletion and drag and drop and appends it to the query input field. | ||||
|      | ||||
|     queryText = Utils.escape(queryText); | ||||
|     prettyQueryText = Utils.escape(prettyQueryText); | ||||
|     let queryChipElement = Utils.HTMLToElement( | ||||
|       ` | ||||
|         <span class="chip query-component" data-type="${dataType}" data-query="${queryText}" draggable="true"> | ||||
|         <span class="chip query-component" data-type="${dataType}" data-query="${queryText}" draggable="true" data-closing-tag="${isClosingTag}"> | ||||
|           ${prettyQueryText} | ||||
|           <i class="material-icons close">close</i> | ||||
|           ${isClosingTag ? '<i class="material-icons" style="padding-top:5px; font-size:20px; cursor:pointer;">lock_open</i>' : '<i class="material-icons close">close</i>'} | ||||
|         </span> | ||||
|       ` | ||||
|     ); | ||||
|  | ||||
|     queryChipElement.addEventListener('click', () => this.selectChipElement(queryChipElement)); | ||||
|     queryChipElement.querySelector('i').addEventListener('click', () => this.deleteChipElement(queryChipElement)); | ||||
|      | ||||
|     this.actionListeners(queryChipElement, isClosingTag); | ||||
|     queryChipElement.addEventListener('dragstart', this.handleDragStart.bind(this, queryChipElement)); | ||||
|     queryChipElement.addEventListener('dragend', this.handleDragEnd); | ||||
|     if (index !== null) { | ||||
|       this.elements.queryInputField.insertBefore(queryChipElement, this.elements.queryChipElements[index]); | ||||
|  | ||||
|     // Ensures that metadata is always at the end of the query and if an index is given, inserts the query chip at the given index and if there is a closing tag, inserts the query chip before the closing tag. | ||||
|     this.removePlaceholder(); | ||||
|     let lastChild = this.elements.queryInputField.lastChild; | ||||
|     let isLastChildTextAnnotation = lastChild && lastChild.dataset.type === 'text-annotation'; | ||||
|     if (!index) { | ||||
|       let closingTagElement = this.elements.queryInputField.querySelector('[data-closing-tag="true"]'); | ||||
|       if (closingTagElement) { | ||||
|         index = Array.from(this.elements.queryInputField.children).indexOf(closingTagElement); | ||||
|       } | ||||
|     } | ||||
|     if (index || isLastChildTextAnnotation) { | ||||
|       let insertingElement = isLastChildTextAnnotation ? lastChild : this.elements.queryChipElements[index]; | ||||
|       this.elements.queryInputField.insertBefore(queryChipElement, insertingElement); | ||||
|     } else { | ||||
|       this.elements.queryInputField.appendChild(queryChipElement); | ||||
|     } | ||||
|  | ||||
|     this.updateChipList(); | ||||
|     this.queryPreviewBuilder(); | ||||
|   } | ||||
|  | ||||
|   actionListeners(queryChipElement, isClosingTag) { | ||||
|     let notQuantifiableDataTypes = ['start-sentence', 'end-sentence', 'start-entity', 'start-empty-entity', 'end-entity', 'token-incidence-modifier']; | ||||
|     queryChipElement.addEventListener('click', (event) => { | ||||
|       if (event.target.classList.contains('chip')) { | ||||
|         if (!notQuantifiableDataTypes.includes(queryChipElement.dataset.type)) { | ||||
|           this.selectChipElement(queryChipElement); | ||||
|         } | ||||
|       } | ||||
|     }); | ||||
|     queryChipElement.querySelector('i').addEventListener('click', () => { | ||||
|       if (isClosingTag) { | ||||
|         this.lockClosingChipElement(queryChipElement); | ||||
|       } else { | ||||
|         this.deleteChipElement(queryChipElement); | ||||
|       } | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   lockClosingChipElement(queryChipElement) { | ||||
|     let chipIndex = Array.from(this.elements.queryInputField.children).indexOf(queryChipElement); | ||||
|     this.queryChipFactory(queryChipElement.dataset.type, queryChipElement.firstChild.textContent, queryChipElement.dataset.query, chipIndex+1); | ||||
|     this.deleteChipElement(queryChipElement); | ||||
|     this.updateChipList(); | ||||
|   } | ||||
|  | ||||
|   handleDragStart(queryChipElement, event) { | ||||
|     // is called when a query chip is dragged. It creates a dropzone (in form of a chip) for the dragged chip and adds it to the query input field. | ||||
|     let queryChips = this.elements.queryInputField.querySelectorAll('.query-component'); | ||||
|     setTimeout(() => { | ||||
|       let targetChipElement = Utils.HTMLToElement('<span class="chip drop-target">Drop here</span>'); | ||||
| @@ -81,6 +141,7 @@ class GeneralFunctionsQueryBuilder { | ||||
|   } | ||||
|  | ||||
|   queryPreviewBuilder() { | ||||
|     // Builds the query preview in the form of pure CQL and displays it in the query preview field. | ||||
|     let queryPreview = document.querySelector('#corpus-analysis-concordance-query-preview'); | ||||
|     let queryInputFieldContent = []; | ||||
|     this.elements.queryChipElements.forEach(element => { | ||||
| @@ -92,17 +153,15 @@ class GeneralFunctionsQueryBuilder { | ||||
|     }); | ||||
|    | ||||
|     let queryString = queryInputFieldContent.join(' '); | ||||
|     if (queryString.includes(' +')) { | ||||
|       queryString = queryString.replace(/ \+/g, '+'); | ||||
|     } | ||||
|     if (queryString.includes(' *')) { | ||||
|       queryString = queryString.replace(/ \*/g, '*'); | ||||
|     } | ||||
|     if (queryString.includes(' ?')) { | ||||
|       queryString = queryString.replace(/ \?/g, '?'); | ||||
|     } | ||||
|     if (queryString.includes(' {')) { | ||||
|       queryString = queryString.replace(/ \{/g, '{'); | ||||
|     let replacements = { | ||||
|       ' +': '+', | ||||
|       ' *': '*', | ||||
|       ' ?': '?', | ||||
|       ' {': '{' | ||||
|     }; | ||||
|  | ||||
|     for (let key in replacements) { | ||||
|       queryString = queryString.replace(key, replacements[key]); | ||||
|     } | ||||
|     queryString += ';'; | ||||
|    | ||||
| @@ -117,6 +176,9 @@ class GeneralFunctionsQueryBuilder { | ||||
|       this.elements.entityElement.innerHTML = 'Entity'; | ||||
|     } | ||||
|     this.elements.queryInputField.removeChild(attr); | ||||
|     if (this.elements.queryInputField.children.length === 0) { | ||||
|       this.addPlaceholder(); | ||||
|     } | ||||
|     this.updateChipList(); | ||||
|     this.queryPreviewBuilder(); | ||||
|   } | ||||
| @@ -135,6 +197,7 @@ class GeneralFunctionsQueryBuilder { | ||||
|   } | ||||
|  | ||||
|   tokenIncidenceModifierHandler(incidenceModifier, incidenceModifierPretty) { | ||||
|     // Adds a token incidence modifier to the query input field. | ||||
|     let selectedChip = this.elements.queryInputField.querySelector('.chip.teal'); | ||||
|     let selectedChipIndex = Array.from(this.elements.queryInputField.children).indexOf(selectedChip); | ||||
|     this.queryChipFactory('token-incidence-modifier', incidenceModifierPretty, incidenceModifier, selectedChipIndex+1); | ||||
| @@ -142,6 +205,7 @@ class GeneralFunctionsQueryBuilder { | ||||
|   } | ||||
|  | ||||
|   tokenNMSubmitHandler(modalId) { | ||||
|     // Adds a token incidence modifier (exactly n or between n and m) to the query input field. | ||||
|     let modal = document.querySelector(`#${modalId}`); | ||||
|     let input_n = modal.querySelector('.n-m-input[data-value-type="n"]').value; | ||||
|     let input_m = modal.querySelector('.n-m-input[data-value-type="m"]') || undefined; | ||||
|   | ||||
| @@ -10,24 +10,22 @@ class StructuralAttributeBuilderFunctionsQueryBuilder extends GeneralFunctionsQu | ||||
|     }); | ||||
|     document.querySelector('.ent-type-selection-action[data-ent-type="any"]').addEventListener('click', () => { | ||||
|       this.queryChipFactory('start-empty-entity', 'Entity Start', '<ent>'); | ||||
|       this.queryChipFactory('end-entity', 'Entity End', '</ent>'); | ||||
|       this.elements.structuralAttrModal.close(); | ||||
|       this.queryChipFactory('end-entity', 'Entity End', '</ent>', null, true); | ||||
|       this.resetAndCloseStructuralAttrModal(); | ||||
|     }); | ||||
|     document.querySelector('.ent-type-selection-action[data-ent-type="english"]').addEventListener('change', (event) => { | ||||
|       this.queryChipFactory('start-entity', `Entity Type=${event.target.value}`, `<ent_type="${event.target.value}">`); | ||||
|       this.queryChipFactory('end-entity', 'Entity End', '</ent_type>'); | ||||
|       this.elements.structuralAttrModal.close(); | ||||
|       this.queryChipFactory('end-entity', 'Entity End', '</ent_type>', null, true); | ||||
|       this.resetAndCloseStructuralAttrModal(); | ||||
|     }); | ||||
|  | ||||
|  | ||||
|   } | ||||
|  | ||||
|   actionButtonInStrucAttrModalHandler(action) { | ||||
|     switch (action) { | ||||
|       case 'sentence': | ||||
|         this.queryChipFactory('start-sentence', 'Sentence Start', '<s>'); | ||||
|         this.queryChipFactory('end-sentence', 'Sentence End', '</s>'); | ||||
|         this.elements.structuralAttrModal.close(); | ||||
|         this.queryChipFactory('end-sentence', 'Sentence End', '</s>', null, true); | ||||
|         this.resetAndCloseStructuralAttrModal(); | ||||
|         break; | ||||
|       case 'entity': | ||||
|         this.toggleClass(['entity-builder'], 'hide', 'toggle'); | ||||
| @@ -42,4 +40,36 @@ class StructuralAttributeBuilderFunctionsQueryBuilder extends GeneralFunctionsQu | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   textAnnotationSubmitHandler() { | ||||
|     let noValueMetadataMessage = document.querySelector('#corpus-analysis-concordance-no-value-metadata-message'); | ||||
|     let textAnnotationSubmit = document.querySelector('#corpus-analysis-concordance-text-annotation-submit'); | ||||
|     let textAnnotationInput = document.querySelector('#corpus-analysis-concordance-text-annotation-input'); | ||||
|     let textAnnotationOptions = document.querySelector('#corpus-analysis-concordance-text-annotation-options'); | ||||
|  | ||||
|     if (textAnnotationInput.value === '') { | ||||
|       textAnnotationSubmit.classList.add('red'); | ||||
|       noValueMetadataMessage.classList.remove('hide'); | ||||
|       setTimeout(() => { | ||||
|         textAnnotationSubmit.classList.remove('red'); | ||||
|       }, 500); | ||||
|       setTimeout(() => { | ||||
|         noValueMetadataMessage.classList.add('hide'); | ||||
|       }, 3000); | ||||
|     } else { | ||||
|       let queryText = `:: match.text_${textAnnotationOptions.value}="${textAnnotationInput.value}"`; | ||||
|       this.queryChipFactory('text-annotation', `${textAnnotationOptions.value}=${textAnnotationInput.value}`, queryText); | ||||
|       this.resetAndCloseStructuralAttrModal(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   resetAndCloseStructuralAttrModal() { | ||||
|     let textAnnotatinInput = document.querySelector('#corpus-analysis-concordance-text-annotation-input'); | ||||
|     textAnnotatinInput.value = ''; | ||||
|     this.resetMaterializeSelection([this.elements.englishEntTypeSelection, this.elements.germanEntTypeSelection]); | ||||
|     this.resetMaterializeSelection([this.elements.textAnnotationSelection], 'address'); | ||||
|  | ||||
|     this.toggleClass(['entity-builder', 'text-annotation-builder'], 'hide', 'add'); | ||||
|     this.elements.structuralAttrModal.close(); | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -331,13 +331,4 @@ class TokenAttributeBuilderFunctionsQueryBuilder extends GeneralFunctionsQueryBu | ||||
|     this.resetMaterializeSelection([this.elements.englishPosSelection, this.elements.germanPosSelection, this.elements.simplePosSelection]); | ||||
|     this.resetMaterializeSelection([this.elements.positionalAttrSelection], "word"); | ||||
|   } | ||||
|  | ||||
|   resetMaterializeSelection(selectionElements, value = "default") { | ||||
|     selectionElements.forEach(selectionElement => { | ||||
|       selectionElement.querySelector(`option[value=${value}]`).selected = true; | ||||
|       let instance = M.FormSelect.getInstance(selectionElement); | ||||
|       instance.destroy(); | ||||
|       M.FormSelect.init(selectionElement); | ||||
|     }) | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -16,6 +16,26 @@ class Utils { | ||||
|     }); | ||||
|   }; | ||||
|  | ||||
|   static unescape(escapedText) { | ||||
|     var table = { | ||||
|       'lt': '<', | ||||
|       'gt': '>', | ||||
|       'quot': '"', | ||||
|       'apos': "'", | ||||
|       'amp': '&', | ||||
|       '#10': '\r', | ||||
|       '#13': '\n' | ||||
|     }; | ||||
|      | ||||
|     return escapedText.replace(/&(#?\w+);/g, (match, entity) => { | ||||
|       if (table.hasOwnProperty(entity)) { | ||||
|         return table[entity]; | ||||
|       } | ||||
|        | ||||
|       return match; | ||||
|     }); | ||||
| } | ||||
|  | ||||
|   static HTMLToElement(HTMLString) { | ||||
|     let templateElement = document.createElement('template'); | ||||
|     templateElement.innerHTML = HTMLString.trim(); | ||||
|   | ||||
| @@ -2,7 +2,9 @@ | ||||
| <form id="corpus-analysis-concordance-query-builder-form"> | ||||
|   <div class="row"> | ||||
|     <div class="col s9" id="corpus-analysis-concordance-query-builder-input-field-container"> | ||||
|       <div id="corpus-analysis-concordance-query-builder-input-field"></div> | ||||
|       <div id="corpus-analysis-concordance-query-builder-input-field"> | ||||
|         <p id="corpus-analysis-concordance-query-builder-input-field-placeholder">Click on the buttons below to build your query.</p> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div class="input-field col s3"> | ||||
|       <i class="material-icons prefix">arrow_forward</i> | ||||
| @@ -75,8 +77,8 @@ | ||||
|         <a class="btn waves-effect waves-light col ent-type-selection-action" data-ent-type="any">Add Entity of any type</a> | ||||
|         <p class="col s1 l1"></p> | ||||
|         <div class= "input-field col s3"> | ||||
|             <select name="englishenttype" class="ent-type-selection-action" data-ent-type="english"> | ||||
|               <option value="" disabled selected>English ent_type</option> | ||||
|             <select id="corpus-analysis-concordance-english-ent-type-selection" name="englishenttype" class="ent-type-selection-action" data-ent-type="english"> | ||||
|               <option value="default" disabled selected>English ent_type</option> | ||||
|               <option value="CARDINAL">CARDINAL</option> | ||||
|               <option value="DATE">DATE</option> | ||||
|               <option value="EVENT">EVENT</option> | ||||
| @@ -99,8 +101,8 @@ | ||||
|             <label>Entity Type</label> | ||||
|         </div> | ||||
|         <div class= "input-field col s3"> | ||||
|             <select name="germanenttype" class="ent-type-selection-action" data-ent-type="german"> | ||||
|               <option value="" disabled selected>German ent_type</option> | ||||
|             <select id="corpus-analysis-concordance-german-ent-type-selection" name="germanenttype" class="ent-type-selection-action" data-ent-type="german"> | ||||
|               <option value="default" disabled selected>German ent_type</option> | ||||
|               <option value="LOC">LOC</option> | ||||
|               <option value="MISC">MISC</option> | ||||
|               <option value="ORG">ORG</option> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user