1441 |
ariadna |
1 |
{"version":3,"file":"embedinsert.min.js","sources":["../../src/embed/embedinsert.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Tiny media plugin embed upload class.\n *\n * This handles the embed upload using url, drag-drop and repositories.\n *\n * @module tiny_media/embed/embedinsert\n * @copyright 2024 Stevani Andolo <stevani@hotmail.com.au>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {prefetchStrings} from 'core/prefetch';\nimport {getStrings} from 'core/str';\nimport {component} from \"../common\";\nimport {\n setPropertiesFromData,\n startMediaLoading,\n stopMediaLoading,\n showElements,\n} from '../helpers';\nimport Selectors from \"../selectors\";\nimport Dropzone from 'core/dropzone';\nimport uploadFile from 'editor_tiny/uploader';\nimport {EmbedHandler} from './embedhandler';\nimport {\n getMediaTitle,\n mediaDetailsTemplateContext,\n checkMediaType,\n fetchPreview,\n} from './embedhelpers';\nimport {EmbedPreview} from './embedpreview';\n\nprefetchStrings(component, [\n 'insertmedia',\n 'addmediafilesdrop',\n 'uploading',\n 'loadingmedia',\n]);\n\nexport class EmbedInsert {\n\n constructor(data) {\n setPropertiesFromData(this, data); // Creates dynamic properties based on \"data\" param.\n }\n\n /**\n * Init the dropzone and lang strings.\n */\n init = async() => {\n const langStringKeys = [\n 'insertmedia',\n 'addmediafilesdrop',\n 'uploading',\n 'loadingmedia',\n ];\n const langStringValues = await getStrings([...langStringKeys].map((key) => ({key, component})));\n this.langStrings = Object.fromEntries(langStringKeys.map((key, index) => [key, langStringValues[index]]));\n this.currentModal.setTitle(this.langStrings.insertmedia);\n\n // Let's init the dropzone if canShowDropZone is true and mediaType is null.\n if (this.canShowDropZone && !this.mediaType) {\n const dropZoneEle = document.querySelector(Selectors.EMBED.elements.dropzoneContainer);\n const dropZone = new Dropzone(\n dropZoneEle,\n this.acceptedMediaTypes,\n files => {\n this.handleUploadedFile(files);\n }\n );\n\n dropZone.setLabel(this.langStrings.addmediafilesdrop);\n dropZone.init();\n }\n };\n\n /**\n * Loads and displays a preview media based on the provided URL, and handles media loading events.\n *\n * @param {string} url - The URL of the media to load and display.\n */\n loadMediaPreview = async(url) => {\n this.originalUrl = url;\n this.fetchedMediaLinkTitle = await getMediaTitle(url, this);\n\n if (this.newMediaLink) { // Media added using url input.\n this.filteredContent = await fetchPreview(this.originalUrl, this.contextId);\n\n if (!this.mediaType) {\n // It means the url points to a physical media file.\n if (this.fetchedMediaLinkTitle) {\n // Case-insensitive regex for video tag.\n const videoRegex = /<video[^>]*>.*<\\/video>/i;\n // Case-insensitive regex for audio tag.\n const audioRegex = /<audio[^>]*>.*<\\/audio>/i;\n\n if (videoRegex.test(this.filteredContent)) {\n this.mediaType = 'video';\n } else if (audioRegex.test(this.filteredContent)) {\n this.mediaType = 'audio';\n }\n } else {\n this.mediaType = 'link';\n }\n }\n\n // Process the media preview.\n this.processMediaPreview();\n } else { // Media added using dropzone or repositories.\n this.mediaType ??= await checkMediaType(url);\n\n // Process the media preview.\n this.processMediaPreview();\n }\n };\n\n /**\n * Process the media preview.\n */\n processMediaPreview = async() => {\n // Let's combine the props.\n setPropertiesFromData(\n this,\n await (new EmbedHandler(this)).getMediaTemplateContext()\n );\n\n // Construct templateContext for embed preview.\n const templateContext = await mediaDetailsTemplateContext(this);\n\n if (this.isUpdating && !this.newMediaLink) {\n // Will be used to set the media title if it's in update state.\n this.mediaTitle = templateContext.media.title;\n }\n\n // Load the media details and preview of the selected media.\n (new EmbedHandler(this)).loadMediaDetails(new EmbedPreview(this), templateContext);\n };\n\n /**\n * Updates the content of the loader icon.\n *\n * @param {HTMLElement} root - The root element containing the loader icon.\n * @param {object} langStrings - An object containing language strings.\n * @param {number|null} progress - The progress percentage (optional).\n * @returns {void}\n */\n updateLoaderIcon = (root, langStrings, progress = null) => {\n const loaderIconState = root.querySelector(Selectors.EMBED.elements.loaderIconContainer + ' div');\n loaderIconState.innerHTML = (progress !== null) ?\n `${langStrings.uploading} ${Math.round(progress)}%` :\n langStrings.loadingmedia;\n };\n\n /**\n * Handles media preview on file picker callback.\n *\n * @param {object} params Object of uploaded file\n */\n filePickerCallback = (params) => {\n if (params.url) {\n if (this.mediaType) {\n // Set mediaType to \"null\" if it started with viewing embedded link, otherwise it will not be consistent.\n this.mediaType = null;\n }\n\n // Flag as new file upload.\n this.newFileUpload = true;\n\n // Load the media preview.\n this.loadMediaPreview(params.url);\n }\n };\n\n /**\n * Handles the uploaded file, initiates the upload process, and updates the UI during the upload.\n *\n * @param {FileList} files - The list of files to upload (usually from a file input field).\n * @returns {Promise<void>} A promise that resolves when the file is uploaded and processed.\n */\n handleUploadedFile = async(files) => {\n try {\n startMediaLoading(this.root, Selectors.EMBED.type);\n const fileURL = await uploadFile(this.editor, 'media', files[0], files[0].name, (progress) => {\n this.updateLoaderIcon(this.root, this.langStrings, progress);\n });\n\n // Set the loader icon content to \"loading\" after the file upload completes.\n this.updateLoaderIcon(this.root, this.langStrings);\n this.filePickerCallback({url: fileURL});\n } catch (error) {\n // Handle the error.\n const urlWarningLabelEle = this.root.querySelector(Selectors.EMBED.elements.urlWarning);\n urlWarningLabelEle.innerHTML = error.error !== undefined ? error.error : error;\n showElements(Selectors.EMBED.elements.urlWarning, this.root);\n stopMediaLoading(this.root, Selectors.EMBED.type);\n }\n };\n}\n"],"names":["component","constructor","data","async","langStringKeys","langStringValues","map","key","langStrings","Object","fromEntries","index","currentModal","setTitle","this","insertmedia","canShowDropZone","mediaType","dropZoneEle","document","querySelector","Selectors","EMBED","elements","dropzoneContainer","dropZone","Dropzone","acceptedMediaTypes","files","handleUploadedFile","setLabel","addmediafilesdrop","init","originalUrl","url","fetchedMediaLinkTitle","newMediaLink","filteredContent","contextId","audioRegex","test","processMediaPreview","EmbedHandler","getMediaTemplateContext","templateContext","isUpdating","mediaTitle","media","title","loadMediaDetails","EmbedPreview","root","progress","loaderIconState","loaderIconContainer","innerHTML","uploading","Math","round","loadingmedia","params","newFileUpload","loadMediaPreview","type","fileURL","editor","name","updateLoaderIcon","filePickerCallback","error","urlWarning","undefined"],"mappings":"0zBA8CgBA,kBAAW,CACvB,cACA,oBACA,YACA,4CAKAC,YAAYC,mCAOLC,gBACGC,eAAiB,CACnB,cACA,oBACA,YACA,gBAEEC,uBAAyB,mBAAW,IAAID,gBAAgBE,KAAKC,OAAUA,IAAAA,IAAKP,UAAAA,+BAC7EQ,YAAcC,OAAOC,YAAYN,eAAeE,KAAI,CAACC,IAAKI,QAAU,CAACJ,IAAKF,iBAAiBM,gBAC3FC,aAAaC,SAASC,KAAKN,YAAYO,aAGxCD,KAAKE,kBAAoBF,KAAKG,UAAW,OACnCC,YAAcC,SAASC,cAAcC,mBAAUC,MAAMC,SAASC,mBAC9DC,SAAW,IAAIC,kBACjBR,YACAJ,KAAKa,oBACLC,aACSC,mBAAmBD,UAIhCH,SAASK,SAAShB,KAAKN,YAAYuB,mBACnCN,SAASO,oDASE7B,MAAAA,cACV8B,YAAcC,SACdC,4BAA8B,+BAAcD,IAAKpB,MAElDA,KAAKsB,aAAc,SACdC,sBAAwB,8BAAavB,KAAKmB,YAAanB,KAAKwB,YAE5DxB,KAAKG,aAEFH,KAAKqB,sBAAuB,OAItBI,WAAa,2BAFA,2BAIJC,KAAK1B,KAAKuB,sBAChBpB,UAAY,QACVsB,WAAWC,KAAK1B,KAAKuB,wBACvBpB,UAAY,mBAGhBA,UAAY,YAKpBwB,0BACF,kDACExB,4CAAAA,gBAAoB,gCAAeiB,WAGnCO,sEAOStC,6CAGdW,WACO,IAAI4B,2BAAa5B,MAAO6B,iCAI7BC,sBAAwB,6CAA4B9B,MAEtDA,KAAK+B,aAAe/B,KAAKsB,oBAEpBU,WAAaF,gBAAgBG,MAAMC,WAIvCN,2BAAa5B,MAAOmC,iBAAiB,IAAIC,2BAAapC,MAAO8B,6DAWnD,SAACO,KAAM3C,iBAAa4C,gEAAW,WACxCC,gBAAkBF,KAAK/B,cAAcC,mBAAUC,MAAMC,SAAS+B,oBAAsB,QAC1FD,gBAAgBE,UAA0B,OAAbH,mBACH5C,YAAYgD,sBAAaC,KAAKC,MAAMN,eACvC5C,YAAYmD,2DAQjBC,SACdA,OAAO1B,MACHpB,KAAKG,iBAEAA,UAAY,WAIhB4C,eAAgB,OAGhBC,iBAAiBF,OAAO1B,oDAUhB/B,MAAAA,2CAEKW,KAAKqC,KAAM9B,mBAAUC,MAAMyC,YACvCC,cAAgB,qBAAWlD,KAAKmD,OAAQ,QAASrC,MAAM,GAAIA,MAAM,GAAGsC,MAAOd,gBACxEe,iBAAiBrD,KAAKqC,KAAMrC,KAAKN,YAAa4C,kBAIlDe,iBAAiBrD,KAAKqC,KAAMrC,KAAKN,kBACjC4D,mBAAmB,CAAClC,IAAK8B,UAChC,MAAOK,OAEsBvD,KAAKqC,KAAK/B,cAAcC,mBAAUC,MAAMC,SAAS+C,YACzDf,eAA4BgB,IAAhBF,MAAMA,MAAsBA,MAAMA,MAAQA,gCAC5DhD,mBAAUC,MAAMC,SAAS+C,WAAYxD,KAAKqC,oCACtCrC,KAAKqC,KAAM9B,mBAAUC,MAAMyC,6CAvJ1BjD,KAAMZ"}
|