1313 * @since 2023-03-05
1414 */
1515
16+ import { Modal } from 'bootstrap' ;
17+ import { fetchMarkdownContent , fetchMediaBrowserContent } from '../api' ;
18+ import { MediaBrowserApiResponse , Response } from '../interfaces' ;
19+
1620export const handleMarkdownForm = ( ) : void => {
1721 const answerHeight = localStorage . getItem ( 'phpmyfaq.answer.height' ) ;
18- const answer = document . getElementById ( 'answer-markdown' ) as HTMLTextAreaElement | null ;
19- const markdownTabs = document . getElementById ( 'markdown-tabs' ) ;
22+ const answer = document . getElementById ( 'answer-markdown' ) as HTMLTextAreaElement ;
23+ const markdownTabs = document . getElementById ( 'markdown-tabs' ) as HTMLElement ;
24+ const insertImage = document . getElementById ( 'pmf-markdown-insert-image' ) as HTMLElement ;
25+ const insertImageButton = document . getElementById ( 'pmf-markdown-insert-image-button' ) as HTMLElement ;
2026
2127 // Store the height of the textarea
2228 if ( answer ) {
@@ -29,34 +35,18 @@ export const handleMarkdownForm = (): void => {
2935 } ) ;
3036 }
3137
32- // handle the Markdown preview
38+ // Handle the Markdown preview
3339 if ( markdownTabs ) {
34- const tab = document . querySelector ( 'a[data-markdown-tab="preview"]' ) as HTMLElement | null ;
40+ const tab = document . querySelector ( 'a[data-markdown-tab="preview"]' ) as HTMLElement ;
3541
3642 if ( tab ) {
3743 tab . addEventListener ( 'shown.bs.tab' , async ( ) => {
38- const preview = document . getElementById ( 'markdown-preview' ) as HTMLElement | null ;
44+ const preview = document . getElementById ( 'markdown-preview' ) as HTMLElement ;
3945 if ( preview && answer ) {
4046 preview . style . height = answer . style . height ;
41-
4247 try {
43- const response = await fetch ( window . location . pathname + 'api/content/markdown' , {
44- method : 'POST' ,
45- headers : {
46- Accept : 'application/json, text/plain, */*' ,
47- 'Content-Type' : 'application/json' ,
48- } ,
49- body : JSON . stringify ( {
50- text : answer . value ,
51- } ) ,
52- } ) ;
53-
54- if ( ! response . ok ) {
55- throw new Error ( 'Network response was not ok' ) ;
56- }
57-
58- const responseData = await response . json ( ) ;
59- preview . innerHTML = responseData . success ;
48+ const response = ( await fetchMarkdownContent ( answer . value ) ) as unknown as Response ;
49+ preview . innerHTML = response . success ;
6050 } catch ( error ) {
6151 if ( error instanceof Error ) {
6252 console . error ( error ) ;
@@ -68,4 +58,58 @@ export const handleMarkdownForm = (): void => {
6858 } ) ;
6959 }
7060 }
61+
62+ // Handle inserting images from Modal
63+ if ( insertImage ) {
64+ const container = document . getElementById ( 'pmf-markdown-insert-image-modal' ) as HTMLElement ;
65+ const modal = new Modal ( container ) ;
66+ insertImage . addEventListener ( 'click' , async ( event : Event ) : Promise < void > => {
67+ event . preventDefault ( ) ;
68+ modal . show ( ) ;
69+
70+ const response = ( await fetchMediaBrowserContent ( ) ) as MediaBrowserApiResponse ;
71+
72+ if ( response . success ) {
73+ const list = document . getElementById ( 'pmf-markdown-insert-image-list' ) as HTMLElement ;
74+ list . innerHTML = '' ; // Clear previous content
75+
76+ response . data . sources . forEach ( ( source ) : void => {
77+ source . files . forEach ( ( file ) => {
78+ const listItem = document . createElement ( 'div' ) as HTMLElement ;
79+ listItem . classList . add ( 'list-group-item' , 'd-flex' , 'align-items-center' ) ;
80+ listItem . innerHTML = `
81+ <div class="form-check me-2">
82+ <input type="checkbox" class="form-check-input" id="checkbox-${ file . file } " data-image-url="${ source . baseurl } /${ source . path } /${ file . file } ">
83+ <label class="form-check-label d-none" for="checkbox-${ file . file } " aria-hidden="true">Select</label>
84+ </div>
85+ <img src="${ source . baseurl } /${ source . path } /${ file . file } " class="img-thumbnail" alt="${ file . file } " style="height: 100px;">
86+ ` ;
87+ list . appendChild ( listItem ) ;
88+ } ) ;
89+ } ) ;
90+ }
91+ } ) ;
92+
93+ // Add event listener to the insert image button
94+ insertImageButton . addEventListener ( 'click' , ( ) => {
95+ const checkboxes = document . querySelectorAll ( '.form-check-input:checked' ) as NodeListOf < HTMLInputElement > ;
96+ let markdownImages : string = '' ;
97+
98+ checkboxes . forEach ( ( checkbox : HTMLInputElement ) : void => {
99+ const imageUrl = ( checkbox as HTMLInputElement ) . dataset . imageUrl as string ;
100+ if ( imageUrl ) {
101+ markdownImages += `\n` ;
102+ }
103+ } ) ;
104+
105+ // Insert the Markdown images at the cursor position
106+ const startPos : number = answer . selectionStart ;
107+ const endPos : number = answer . selectionEnd ;
108+ answer . value = answer . value . substring ( 0 , startPos ) + markdownImages + answer . value . substring ( endPos ) ;
109+ answer . setSelectionRange ( startPos + markdownImages . length , startPos + markdownImages . length ) ;
110+ answer . focus ( ) ;
111+
112+ modal . hide ( ) ;
113+ } ) ;
114+ }
71115} ;
0 commit comments