mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	select template when creating note, closes #2813
This commit is contained in:
		
							
								
								
									
										94
									
								
								src/public/app/dialogs/note_type_chooser.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								src/public/app/dialogs/note_type_chooser.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | |||||||
|  | import noteTypesService from "../services/note_types.js"; | ||||||
|  |  | ||||||
|  | const $dialog = $("#note-type-chooser-dialog"); | ||||||
|  | const $noteTypeDropdown = $("#note-type-dropdown"); | ||||||
|  | const $noteTypeDropdownTrigger = $("#note-type-dropdown-trigger"); | ||||||
|  | $noteTypeDropdownTrigger.dropdown(); | ||||||
|  |  | ||||||
|  | let resolve; | ||||||
|  | let $originalFocused; // element focused before the dialog was opened, so we can return to it afterwards | ||||||
|  | let $originalDialog; | ||||||
|  |  | ||||||
|  | export async function chooseNoteType() { | ||||||
|  |     $originalFocused = $(':focus'); | ||||||
|  |  | ||||||
|  |     const noteTypes = await noteTypesService.getNoteTypeItems(); | ||||||
|  |  | ||||||
|  |     $noteTypeDropdown.empty(); | ||||||
|  |  | ||||||
|  |     for (const noteType of noteTypes) { | ||||||
|  |         if (noteType.title === '----') { | ||||||
|  |             $noteTypeDropdown.append($('<h6 class="dropdown-header">').append("Templates:")); | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             $noteTypeDropdown.append( | ||||||
|  |                 $('<a class="dropdown-item" tabindex="0">') | ||||||
|  |                     .attr("data-note-type", noteType.type) | ||||||
|  |                     .attr("data-template-note-id", noteType.templateNoteId) | ||||||
|  |                     .append($("<span>").addClass(noteType.uiIcon)) | ||||||
|  |                     .append(" " + noteType.title) | ||||||
|  |             ); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $noteTypeDropdownTrigger.dropdown('show'); | ||||||
|  |  | ||||||
|  |     $originalDialog = glob.activeDialog; | ||||||
|  |     glob.activeDialog = $dialog; | ||||||
|  |     $dialog.modal(); | ||||||
|  |  | ||||||
|  |     $noteTypeDropdown.find(".dropdown-item:first").focus(); | ||||||
|  |  | ||||||
|  |     return new Promise((res, rej) => { resolve = res; }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $dialog.on("hidden.bs.modal", () => { | ||||||
|  |     if (resolve) { | ||||||
|  |         resolve({success: false}); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if ($originalFocused) { | ||||||
|  |         $originalFocused.trigger('focus'); | ||||||
|  |         $originalFocused = null; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     glob.activeDialog = $originalDialog; | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | function doResolve(e) { | ||||||
|  |     const $item = $(e.target).closest(".dropdown-item"); | ||||||
|  |     const noteType = $item.attr("data-note-type"); | ||||||
|  |     const templateNoteId = $item.attr("data-template-note-id"); | ||||||
|  |  | ||||||
|  |     resolve({ | ||||||
|  |         success: true, | ||||||
|  |         noteType, | ||||||
|  |         templateNoteId | ||||||
|  |     }); | ||||||
|  |     resolve = null; | ||||||
|  |  | ||||||
|  |     $dialog.modal("hide"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $noteTypeDropdown.on('click', '.dropdown-item', e => doResolve(e)); | ||||||
|  |  | ||||||
|  | $noteTypeDropdown.on('focus', '.dropdown-item', e => { | ||||||
|  |     $noteTypeDropdown.find('.dropdown-item').each((i, el) => { | ||||||
|  |         $(el).toggleClass('active', el === e.target); | ||||||
|  |     }); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | $noteTypeDropdown.on('keydown', '.dropdown-item', e => { | ||||||
|  |     if (e.key === 'Enter') { | ||||||
|  |         doResolve(e); | ||||||
|  |         e.preventDefault(); | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | $noteTypeDropdown.parent().on('hide.bs.dropdown', e => { | ||||||
|  |     // prevent closing dropdown by clicking outside | ||||||
|  |     if (e.clickEvent) { | ||||||
|  |         e.preventDefault(); | ||||||
|  |     } | ||||||
|  | }); | ||||||
| @@ -170,9 +170,18 @@ function initNoteAutocomplete($el, options) { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (suggestion.action === 'create-note') { |         if (suggestion.action === 'create-note') { | ||||||
|  |             const noteTypeChooserDialog = await import('../dialogs/note_type_chooser.js'); | ||||||
|  |             const {success, noteType, templateNoteId} = await noteTypeChooserDialog.chooseNoteType(); | ||||||
|  |  | ||||||
|  |             if (!success) { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |  | ||||||
|             const {note} = await noteCreateService.createNote(suggestion.parentNoteId, { |             const {note} = await noteCreateService.createNote(suggestion.parentNoteId, { | ||||||
|                 title: suggestion.noteTitle, |                 title: suggestion.noteTitle, | ||||||
|                 activate: false |                 activate: false, | ||||||
|  |                 type: noteType, | ||||||
|  |                 templateNoteId: templateNoteId | ||||||
|             }); |             }); | ||||||
|  |  | ||||||
|             suggestion.notePath = treeService.getSomeNotePath(note); |             suggestion.notePath = treeService.getSomeNotePath(note); | ||||||
|   | |||||||
| @@ -75,6 +75,20 @@ async function createNote(parentNotePath, options = {}) { | |||||||
|     }; |     }; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | async function createNoteWithTypePrompt(parentNotePath, options = {}) { | ||||||
|  |     const noteTypeChooserDialog = await import('../dialogs/note_type_chooser.js'); | ||||||
|  |     const {success, noteType, templateNoteId} = await noteTypeChooserDialog.chooseNoteType(); | ||||||
|  |  | ||||||
|  |     if (!success) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     options.type = noteType; | ||||||
|  |     options.templateNoteId = templateNoteId; | ||||||
|  |  | ||||||
|  |     return await createNote(parentNotePath, options); | ||||||
|  | } | ||||||
|  |  | ||||||
| /* If first element is heading, parse it out and use it as a new heading. */ | /* If first element is heading, parse it out and use it as a new heading. */ | ||||||
| function parseSelectedHtml(selectedHtml) { | function parseSelectedHtml(selectedHtml) { | ||||||
|     const dom = $.parseHTML(selectedHtml); |     const dom = $.parseHTML(selectedHtml); | ||||||
| @@ -106,5 +120,6 @@ async function duplicateSubtree(noteId, parentNotePath) { | |||||||
|  |  | ||||||
| export default { | export default { | ||||||
|     createNote, |     createNote, | ||||||
|  |     createNoteWithTypePrompt, | ||||||
|     duplicateSubtree |     duplicateSubtree | ||||||
| }; | }; | ||||||
|   | |||||||
							
								
								
									
										40
									
								
								src/public/app/services/note_types.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/public/app/services/note_types.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | |||||||
|  | import server from "./server.js"; | ||||||
|  | import froca from "./froca.js"; | ||||||
|  |  | ||||||
|  | async function getNoteTypeItems(command) { | ||||||
|  |     const items = [ | ||||||
|  |         { title: "Text", command: command, type: "text", uiIcon: "bx bx-note" }, | ||||||
|  |         { title: "Code", command: command, type: "code", uiIcon: "bx bx-code" }, | ||||||
|  |         { title: "Saved Search", command: command, type: "search", uiIcon: "bx bx-file-find" }, | ||||||
|  |         { title: "Relation Map", command: command, type: "relation-map", uiIcon: "bx bx-map-alt" }, | ||||||
|  |         { title: "Note Map", command: command, type: "note-map", uiIcon: "bx bx-map-alt" }, | ||||||
|  |         { title: "Render Note", command: command, type: "render", uiIcon: "bx bx-extension" }, | ||||||
|  |         { title: "Book", command: command, type: "book", uiIcon: "bx bx-book" }, | ||||||
|  |         { title: "Mermaid Diagram", command: command, type: "mermaid", uiIcon: "bx bx-selection" }, | ||||||
|  |         { title: "Canvas", command: command, type: "canvas", uiIcon: "bx bx-pen" }, | ||||||
|  |         { title: "Web View", command: command, type: "iframe", uiIcon: "bx bx-globe-alt" }, | ||||||
|  |     ]; | ||||||
|  |  | ||||||
|  |     const templateNoteIds = await server.get("search-templates"); | ||||||
|  |     const templateNotes = await froca.getNotes(templateNoteIds); | ||||||
|  |  | ||||||
|  |     if (items.length > 0) { | ||||||
|  |         items.push({ title: "----" }); | ||||||
|  |  | ||||||
|  |         for (const templateNote of templateNotes) { | ||||||
|  |             items.push({ | ||||||
|  |                 title: templateNote.title, | ||||||
|  |                 uiIcon: templateNote.getIcon(), | ||||||
|  |                 command: command, | ||||||
|  |                 type: templateNote.type, | ||||||
|  |                 templateNoteId: templateNote.noteId | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return items; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export default { | ||||||
|  |     getNoteTypeItems | ||||||
|  | } | ||||||
| @@ -4,7 +4,7 @@ import clipboard from './clipboard.js'; | |||||||
| import noteCreateService from "./note_create.js"; | import noteCreateService from "./note_create.js"; | ||||||
| import contextMenu from "./context_menu.js"; | import contextMenu from "./context_menu.js"; | ||||||
| import appContext from "./app_context.js"; | import appContext from "./app_context.js"; | ||||||
| import server from "./server.js"; | import noteTypesService from "./note_types.js"; | ||||||
|  |  | ||||||
| class TreeContextMenu { | class TreeContextMenu { | ||||||
|     /** |     /** | ||||||
| @@ -25,40 +25,6 @@ class TreeContextMenu { | |||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async getNoteTypeItems(command) { |  | ||||||
|         const items = [ |  | ||||||
|             { title: "Text", command: command, type: "text", uiIcon: "bx bx-note" }, |  | ||||||
|             { title: "Code", command: command, type: "code", uiIcon: "bx bx-code" }, |  | ||||||
|             { title: "Saved Search", command: command, type: "search", uiIcon: "bx bx-file-find" }, |  | ||||||
|             { title: "Relation Map", command: command, type: "relation-map", uiIcon: "bx bx-map-alt" }, |  | ||||||
|             { title: "Note Map", command: command, type: "note-map", uiIcon: "bx bx-map-alt" }, |  | ||||||
|             { title: "Render Note", command: command, type: "render", uiIcon: "bx bx-extension" }, |  | ||||||
|             { title: "Book", command: command, type: "book", uiIcon: "bx bx-book" }, |  | ||||||
|             { title: "Mermaid Diagram", command: command, type: "mermaid", uiIcon: "bx bx-selection" }, |  | ||||||
|             { title: "Canvas", command: command, type: "canvas", uiIcon: "bx bx-pen" }, |  | ||||||
|             { title: "Web View", command: command, type: "iframe", uiIcon: "bx bx-globe-alt" }, |  | ||||||
|         ]; |  | ||||||
|  |  | ||||||
|         const templateNoteIds = await server.get("search-templates"); |  | ||||||
|         const templateNotes = await froca.getNotes(templateNoteIds); |  | ||||||
|  |  | ||||||
|         if (items.length > 0) { |  | ||||||
|             items.push({ title: "----" }); |  | ||||||
|  |  | ||||||
|             for (const templateNote of templateNotes) { |  | ||||||
|                 items.push({ |  | ||||||
|                     title: templateNote.title, |  | ||||||
|                     uiIcon: templateNote.getIcon(), |  | ||||||
|                     command: command, |  | ||||||
|                     type: templateNote.type, |  | ||||||
|                     templateNoteId: templateNote.noteId |  | ||||||
|                 }); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         return items; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     async getMenuItems() { |     async getMenuItems() { | ||||||
|         const note = await froca.getNote(this.node.data.noteId); |         const note = await froca.getNote(this.node.data.noteId); | ||||||
|         const branch = froca.getBranch(this.node.data.branchId); |         const branch = froca.getBranch(this.node.data.branchId); | ||||||
| @@ -81,10 +47,10 @@ class TreeContextMenu { | |||||||
|             { title: 'Open in a new tab <kbd>Ctrl+Click</kbd>', command: "openInTab", uiIcon: "bx bx-empty", enabled: noSelectedNotes }, |             { title: 'Open in a new tab <kbd>Ctrl+Click</kbd>', command: "openInTab", uiIcon: "bx bx-empty", enabled: noSelectedNotes }, | ||||||
|             { title: 'Open in a new split', command: "openNoteInSplit", uiIcon: "bx bx-dock-right", enabled: noSelectedNotes }, |             { title: 'Open in a new split', command: "openNoteInSplit", uiIcon: "bx bx-dock-right", enabled: noSelectedNotes }, | ||||||
|             { title: 'Insert note after <kbd data-command="createNoteAfter"></kbd>', command: "insertNoteAfter", uiIcon: "bx bx-plus", |             { title: 'Insert note after <kbd data-command="createNoteAfter"></kbd>', command: "insertNoteAfter", uiIcon: "bx bx-plus", | ||||||
|                 items: insertNoteAfterEnabled ? await this.getNoteTypeItems("insertNoteAfter") : null, |                 items: insertNoteAfterEnabled ? await noteTypesService.getNoteTypeItems("insertNoteAfter") : null, | ||||||
|                 enabled: insertNoteAfterEnabled && noSelectedNotes }, |                 enabled: insertNoteAfterEnabled && noSelectedNotes }, | ||||||
|             { title: 'Insert child note <kbd data-command="createNoteInto"></kbd>', command: "insertChildNote", uiIcon: "bx bx-plus", |             { title: 'Insert child note <kbd data-command="createNoteInto"></kbd>', command: "insertChildNote", uiIcon: "bx bx-plus", | ||||||
|                 items: notSearch ? await this.getNoteTypeItems("insertChildNote") : null, |                 items: notSearch ? await noteTypesService.getNoteTypeItems("insertChildNote") : null, | ||||||
|                 enabled: notSearch && noSelectedNotes }, |                 enabled: notSearch && noSelectedNotes }, | ||||||
|             { title: 'Delete <kbd data-command="deleteNotes"></kbd>', command: "deleteNotes", uiIcon: "bx bx-trash", |             { title: 'Delete <kbd data-command="deleteNotes"></kbd>', command: "deleteNotes", uiIcon: "bx bx-trash", | ||||||
|                 enabled: isNotRoot && !isHoisted && parentNotSearch }, |                 enabled: isNotRoot && !isHoisted && parentNotSearch }, | ||||||
|   | |||||||
| @@ -485,7 +485,7 @@ export default class AttributeEditorWidget extends NoteContextAwareWidget { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     async createNoteForReferenceLink(title) { |     async createNoteForReferenceLink(title) { | ||||||
|         const {note} = await noteCreateService.createNote(this.notePath, { |         const {note} = await noteCreateService.createNoteWithTypePrompt(this.notePath, { | ||||||
|             activate: false, |             activate: false, | ||||||
|             title: title |             title: title | ||||||
|         }); |         }); | ||||||
|   | |||||||
| @@ -305,7 +305,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     async createNoteForReferenceLink(title) { |     async createNoteForReferenceLink(title) { | ||||||
|         const {note} = await noteCreateService.createNote(this.notePath, { |         const {note} = await noteCreateService.createNoteWithTypePrompt(this.notePath, { | ||||||
|             activate: false, |             activate: false, | ||||||
|             title: title |             title: title | ||||||
|         }); |         }); | ||||||
|   | |||||||
| @@ -192,6 +192,7 @@ div.ui-tooltip { | |||||||
| .dropdown-menu a:hover:not(.disabled), .dropdown-item:hover:not(.disabled) { | .dropdown-menu a:hover:not(.disabled), .dropdown-item:hover:not(.disabled) { | ||||||
|     color: var(--hover-item-text-color) !important; |     color: var(--hover-item-text-color) !important; | ||||||
|     background-color: var(--hover-item-background-color) !important; |     background-color: var(--hover-item-background-color) !important; | ||||||
|  |     border-color: var(--hover-item-border-color) !important; | ||||||
|     cursor: pointer; |     cursor: pointer; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -210,17 +211,20 @@ div.ui-tooltip { | |||||||
|     padding-bottom: 0; |     padding-bottom: 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| .dropdown-item { | .dropdown-item, .dropdown-header { | ||||||
|     color: var(--menu-text-color) !important; |     color: var(--menu-text-color) !important; | ||||||
|  |     border: 1px solid transparent !important; | ||||||
| } | } | ||||||
|  |  | ||||||
| .dropdown-item.disabled, .dropdown-item.disabled kbd { | .dropdown-item.disabled, .dropdown-item.disabled kbd { | ||||||
|     color: #aaa !important; |     color: #aaa !important; | ||||||
| } | } | ||||||
|  |  | ||||||
| .dropdown-item.active { | .dropdown-item.active, .dropdown-item:focus { | ||||||
|     color: var(--active-item-text-color) !important; |     color: var(--active-item-text-color) !important; | ||||||
|     background-color: var(--active-item-background-color) !important; |     background-color: var(--active-item-background-color) !important; | ||||||
|  |     border-color: var(--active-item-border-color) !important; | ||||||
|  |     outline: none; | ||||||
| } | } | ||||||
|  |  | ||||||
| .CodeMirror { | .CodeMirror { | ||||||
| @@ -473,8 +477,8 @@ table.promoted-attributes-in-tooltip td, table.promoted-attributes-in-tooltip th | |||||||
| } | } | ||||||
|  |  | ||||||
| .algolia-autocomplete .aa-dropdown-menu .aa-suggestion.aa-cursor { | .algolia-autocomplete .aa-dropdown-menu .aa-suggestion.aa-cursor { | ||||||
|     color: var(--hover-item-text-color); |     color: var(--active-item-text-color); | ||||||
|     background-color: var(--hover-item-background-color); |     background-color: var(--active-item-background-color); | ||||||
| } | } | ||||||
|  |  | ||||||
| .help-button { | .help-button { | ||||||
|   | |||||||
| @@ -35,11 +35,13 @@ | |||||||
|     --input-text-color: #ccc; |     --input-text-color: #ccc; | ||||||
|     --input-background-color: #333; |     --input-background-color: #333; | ||||||
|  |  | ||||||
|     --hover-item-text-color: black; |     --hover-item-text-color: #ccc; | ||||||
|     --hover-item-background-color: #777; |     --hover-item-background-color: transparent; | ||||||
|  |     --hover-item-border-color: #aaa; | ||||||
|  |  | ||||||
|     --active-item-text-color: black; |     --active-item-text-color: black; | ||||||
|     --active-item-background-color: #777; |     --active-item-background-color: #777; | ||||||
|  |     --active-item-border-color: transparent; | ||||||
|  |  | ||||||
|     --menu-text-color: white; |     --menu-text-color: white; | ||||||
|     --menu-background-color: #222; |     --menu-background-color: #222; | ||||||
|   | |||||||
| @@ -40,10 +40,12 @@ html { | |||||||
|     --input-background-color: transparent; |     --input-background-color: transparent; | ||||||
|  |  | ||||||
|     --hover-item-text-color: black; |     --hover-item-text-color: black; | ||||||
|     --hover-item-background-color: #ddd; |     --hover-item-background-color: transparent; | ||||||
|  |     --hover-item-border-color: #ccc; | ||||||
|  |  | ||||||
|     --active-item-text-color: black; |     --active-item-text-color: black; | ||||||
|     --active-item-background-color: #ddd; |     --active-item-background-color: #ddd; | ||||||
|  |     --active-item-border-color: transparent; | ||||||
|  |  | ||||||
|     --menu-text-color: black; |     --menu-text-color: black; | ||||||
|     --menu-background-color: white; |     --menu-background-color: white; | ||||||
|   | |||||||
| @@ -41,6 +41,7 @@ | |||||||
| <%- include('dialogs/delete_notes.ejs') %> | <%- include('dialogs/delete_notes.ejs') %> | ||||||
| <%- include('dialogs/password_not_set.ejs') %> | <%- include('dialogs/password_not_set.ejs') %> | ||||||
| <%- include('dialogs/bulk_assign_attributes.ejs') %> | <%- include('dialogs/bulk_assign_attributes.ejs') %> | ||||||
|  | <%- include('dialogs/note_type_chooser.ejs') %> | ||||||
|  |  | ||||||
| <script type="text/javascript"> | <script type="text/javascript"> | ||||||
|     global = globalThis; /* fixes https://github.com/webpack/webpack/issues/10035 */ |     global = globalThis; /* fixes https://github.com/webpack/webpack/issues/10035 */ | ||||||
|   | |||||||
							
								
								
									
										34
									
								
								src/views/dialogs/note_type_chooser.ejs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/views/dialogs/note_type_chooser.ejs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | <style> | ||||||
|  |     #note-type-dropdown { | ||||||
|  |         position: relative; | ||||||
|  |         font-size: large; | ||||||
|  |         padding: 20px; | ||||||
|  |         width: 100%; | ||||||
|  |         margin-top: 15px; | ||||||
|  |         max-height: 80vh; | ||||||
|  |         overflow: auto; | ||||||
|  |     } | ||||||
|  | </style> | ||||||
|  |  | ||||||
|  | <div id="note-type-chooser-dialog" class="modal mx-auto" tabindex="-1" role="dialog"> | ||||||
|  |     <div class="modal-dialog" style="max-width: 500px;" role="document"> | ||||||
|  |         <div class="modal-content"> | ||||||
|  |             <div class="modal-header"> | ||||||
|  |                 <h5 class="modal-title mr-auto">Choose note type</h5> | ||||||
|  |  | ||||||
|  |                 <button type="button" class="close" data-dismiss="modal" aria-label="Close" style="margin-left: 0 !important;"> | ||||||
|  |                     <span aria-hidden="true">×</span> | ||||||
|  |                 </button> | ||||||
|  |             </div> | ||||||
|  |             <div class="modal-body"> | ||||||
|  |                 Choose note type / template of the new note: | ||||||
|  |  | ||||||
|  |                 <div class="dropdown"> | ||||||
|  |                     <button id="note-type-dropdown-trigger" type="button" style="display: none;" data-toggle="dropdown">Dropdown trigger</button> | ||||||
|  |  | ||||||
|  |                     <div id="note-type-dropdown" class="dropdown-menu"></div> | ||||||
|  |                 </div> | ||||||
|  |             </div> | ||||||
|  |         </div> | ||||||
|  |     </div> | ||||||
|  | </div> | ||||||
		Reference in New Issue
	
	Block a user