diff --git a/projects/questionset-editor-library/src/lib/components/assets-browser/assets-browser.component.html b/projects/questionset-editor-library/src/lib/components/assets-browser/assets-browser.component.html new file mode 100644 index 00000000..68475880 --- /dev/null +++ b/projects/questionset-editor-library/src/lib/components/assets-browser/assets-browser.component.html @@ -0,0 +1,131 @@ + +{{selectast}} + + + + {{myast}} + {{allast}} + + + + + + + + + + {{configService.labelConfig?.button_labels?.search_btn_label}} + + {{assetsCount}} + + {{emptySearchMessage}} + + + + + + + + + + + + + + + + + + + {{configService.labelConfig?.button_labels?.search_btn_label}} + + {{assetsCount}} + + {{emptySearchMessage}} + + + + + + + + + + + + + {{configService.labelConfig?.button_labels?.upload_use_btn_label}} + + + + + +{{configService.labelConfig?.lbl?.uploadAndUse}} + + + + + {{chooseOrDragAst}}* + + + + {{configService.labelConfig?.button_labels?.upload_from_computer_btn_label}} + + + {{assetName}} + {{configService.labelConfig?.lbl?.upload}} {{acceptedFileType}} ({{configService.labelConfig?.lbl?.maxFileSize}} + {{astSize}}{{astSizeType}}) + + {{errorMsg}} + + + + + + {{configService.labelConfig?.lbl?.allowedFileTypes}} {{acceptedFileType}} + {{configService.labelConfig?.lbl?.maximumAllowedFileSize}} {{astSize}}{{astSizeType}} + + + {{configService.labelConfig?.lbl?.copyRightsAndLicense}}* + {{termsAndCondition}} + + + + + + + + {{configService.labelConfig?.lbl?.dropChooseFile}} + + + + + + + + + + + + {{configService.labelConfig?.button_labels?.cancel_btn_label}} + + + {{configService.labelConfig?.button_labels?.upload_use_btn_label}} + + + + {{configService.labelConfig?.button_labels?.back_btn_label}} + + + + diff --git a/projects/questionset-editor-library/src/lib/components/assets-browser/assets-browser.component.scss b/projects/questionset-editor-library/src/lib/components/assets-browser/assets-browser.component.scss new file mode 100644 index 00000000..860b81fe --- /dev/null +++ b/projects/questionset-editor-library/src/lib/components/assets-browser/assets-browser.component.scss @@ -0,0 +1,387 @@ +.editorWrapper { + border: 0px solid white; + } + + .editorWrapper.hasError { + border: 1px solid red; + border-radius: 2px; + } + + .characterCount { + text-align: right; + /* background-color: #f2f2f2; + border: 1px solid #c4c4c4; */ + border-top: 0; + padding-right: 7px; + font-size: 11px; + font-weight: bold; + margin-top: -16px; + position: relative + } + + .custom-image img { + border: 1px dotted; + padding: 7px; + margin: 6px; + cursor: pointer; + } + + .resource-image { + height: 180px !important; + } + + .asset_container { + overflow-y: auto; + overflow-x: hidden; + min-height: 300px !important; + max-height: 300px !important; + padding: 5px; + } + + .insert-image-btn { + position: absolute; + z-index: 1; + left: 653px; + background-color: transparent; + padding: 12px 14px !important; + margin-left: 6px; + } + + .insert-image-btn>.icon { + opacity: 1; + } + + .insert-image-btn:active { + background-color: transparent; + } + + .upload-file-section { + display: flex; + height: 240px; + width: 100%; + max-width: 800px; + align-items: center; + justify-content: center; + flex-direction: column; + margin: 0 auto; + background-color: #F5F9FC; + border: 1px dashed #80a7ce; + } + + .upload-file-description p { + color: #999999; + } + + .upload-file-description ul { + margin: 0; + list-style: disc; + } + + .upload-file-description ul li { + margin-bottom: 8px; + } + + .upload-file-description ul li a { + cursor: pointer; + font-size: 12px; + } + + + /* Grid Layout CSS for uploaded image & video section */ + .sb-grid-layout { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); + grid-gap: 16px; + } + + .sb-grid-layout.image { + grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); + } + + .sb-grid-layout.video { + grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); + } + + .sb-grid-layout .sb-video-content .sb-image-section { + height: 96px; + overflow: hidden; + border-radius: 4px; + box-shadow: inset 0 1px 3px 0 rgba(0, 0, 0, 0.5); + } + + .sb-image-section { + .selected-video { + display: none; + } + + &.active { + .selected-video { + position: absolute; + right: 4px; + top: 4px; + color: #07bc81; + font-size: 20px; + display: block; + } + } + } + .sb-grid-layout .sb-video-content .sb-image-section img { + width: 100%; + height: 100%; + cursor: pointer; + } + + .overlay-image { + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.3); + position: absolute; + left: 0; + right: 0; + cursor: pointer; + } + + .overlay-image .play.icon { + position: absolute; + transform: translate(-50%, -50%); + top: 50%; + left: 50%; + color: rgba(255, 255, 255, .6); + font-size: 32px; + cursor: pointer; + } + + + + ::ng-deep { + + .ck-rounded-corners .ck.ck-editor__top .ck-sticky-panel .ck-toolbar, .ck.ck-editor__top .ck-sticky-panel .ck-toolbar.ck-rounded-corners { + border-left: none; + border-right: none; + border-bottom: 1px solid #c4c4c4; + border-radius: 0; + } + + .ck-rounded-corners .ck.ck-editor__main>.ck-editor__editable, .ck.ck-editor__main>.ck-editor__editable.ck-rounded-corners { + border: none; + } + + .ck-dropdown.ck-font-size-dropdown .ck-dropdown__panel { + height: 150px; + overflow-y: scroll; + } + + figure.image.ck-widget { + width: auto; + height: auto; + overflow: visible; + } + + figure.image img { + width: 100%; + } + + figure.image.resize-25 { + width: 25%; + height: auto; + } + figure.image.resize-50 { + width: 50%; + height: auto; + } + figure.image.resize-75 { + width: 75%; + height: auto; + } + figure.image.resize-100 { + width: 100%; + height: auto; + } + figure.table{ + margin : 2.2rem 0 1.5rem 1rem!important; + } + .text-center { text-align: center } + .text-left { text-align: left } + .text-right { text-align: right } + + .fs-8 { font-size: 0.5rem; } + .fs-10 { font-size: 0.625rem; } + .fs-12 { font-size: 0.75rem; } + .fs-14 { font-size: 0.875rem; } + .fs-16 { font-size: 1rem; } + .fs-18 { font-size: 1.125rem; } + .fs-20 { font-size: 1.25rem; } + .fs-22 { font-size: 1.375rem; } + .fs-24 { font-size: 1.5rem; } + .fs-26 { font-size: 1.625rem; } + .fs-28 { font-size: 1.75rem; } + .fs-30 { font-size: 1.875rem; } + .fs-36 { font-size: 2.25rem; } + } + + .upload-image-modal-section { + border-radius: 4px; + width: 100%; + min-height: 130px; + background: #F5F9FC; + border: 1px dashed #024f9d; + } + + .upload-input-button { + input[type="file"] { + position: absolute; + right: 0px; + top: 0px; + font-size: 118px; + margin: 0px; + padding: 0px; + cursor: pointer; + opacity: 0; + height: 100%; + } + } + + .upload-file-section { + display: flex; + height: 240px; + width: 100%; + max-width: 800px; + align-items: center; + justify-content: center; + flex-direction: column; + margin: 0 auto; + background-color: #F5F9FC; + border: 1px dashed #80a7ce; + } + + .qq-uploader.qq-uploader-selector.custom-qq-uploader { + background: inherit; + border-color: none; + border: none; + max-height: inherit; + min-height: inherit; + overflow-y: inherit; + width: 688px; + height: 240px; + display: flex; + justify-content: center; + align-items: center; + } + + .terms-and-condition { + line-height: 14px; + } + + .sb-info-bx{ + padding: 0.4rem !important; + li{ + margin: 0 !important; + padding: 0 !important; + &::before{ + content: "" !important; + } + } + } + + .red{ + color: red; + } + .b-bl{ + border-left: solid 1px #e4e1e1; + } + .sb-form-fields{ + .sb-field-group{ + margin: 1rem 0; + } + .sb-field{ + position: relative; + margin-bottom: 0.5rem; + .sb-form-control{ + border: 1px solid rgba(34,36,38,.15); + width: 100%; + border-radius: .28571429rem; + box-shadow: 0 0 0 0 transparent inset; + padding: .25rem .5rem!important; + } + } + } + @keyframes spinner-border { + to { + transform: rotate(360deg); + } + } + .sb-loading-spinner { + width: 1rem; + height: 1rem; + margin-right: 8px; + border-width: 0.2em; + display: inline-block; + vertical-align: text-bottom; + border: 0.15em solid currentColor; + border-right-color: transparent; + border-radius: 50%; + -webkit-animation: spinner-border 0.75s linear infinite; + animation: spinner-border 0.75s linear infinite; + } + .sb-btn-loading:before { + position: absolute; + content: ""; + top: 50%; + left: 50%; + margin: -0.64285714em 0 0 -0.64285714em; + width: 1.28571429em; + height: 1.28571429em; + border-radius: 500rem; + border: 0.2em solid rgba(0, 0, 0, 0.15); + } + .sb-btn-loading:after { + position: absolute; + content: ""; + top: 50%; + left: 50%; + margin: -0.64285714em 0 0 -0.64285714em; + width: 1.28571429em; + height: 1.28571429em; + -webkit-animation: button-spin 0.6s linear; + animation: button-spin 0.6s linear; + -webkit-animation-iteration-count: infinite; + animation-iteration-count: infinite; + border-radius: 500rem; + border-color: #fff transparent transparent; + border-style: solid; + border-width: 0.2em; + -webkit-box-shadow: 0 0 0 1px transparent; + box-shadow: 0 0 0 1px transparent; + } + .sb-btn-outline-disabled { + background-color: #ffffff; + border: 1px solid #cccccc; + color: #999999; + cursor: default; + font-weight: 400; + } + .sb-color-grey{color:#666;} + + .flex-jc-space-end { + justify-content: flex-end !important; + } + .fs-0785{ + font-size: 0.785rem !important; + } + .ui.info.message{ + color: #276f86 !important; + } + .sb-textbox[disabled="true"]{ + opacity: 0.3 !important; + font-weight: 500 !important; + } + .sb-tabset-segment { + min-height: 288px; + max-height: 288px; + overflow-y: auto; + } + + input:focus-visible{ + border: none !important; + } + \ No newline at end of file diff --git a/projects/questionset-editor-library/src/lib/components/assets-browser/assets-browser.component.spec.ts b/projects/questionset-editor-library/src/lib/components/assets-browser/assets-browser.component.spec.ts new file mode 100644 index 00000000..11de36c0 --- /dev/null +++ b/projects/questionset-editor-library/src/lib/components/assets-browser/assets-browser.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AssetsBrowserComponent } from './assets-browser.component'; + +describe('AssetsBrowserComponent', () => { + let component: AssetsBrowserComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AssetsBrowserComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(AssetsBrowserComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/questionset-editor-library/src/lib/components/assets-browser/assets-browser.component.ts b/projects/questionset-editor-library/src/lib/components/assets-browser/assets-browser.component.ts new file mode 100644 index 00000000..65a23c29 --- /dev/null +++ b/projects/questionset-editor-library/src/lib/components/assets-browser/assets-browser.component.ts @@ -0,0 +1,582 @@ +import { Component, OnInit, AfterViewInit, Output, Input, EventEmitter, OnChanges, ViewChild, ElementRef, OnDestroy } from '@angular/core'; +import * as _ from 'lodash-es'; +import { catchError, map } from 'rxjs/operators'; +import { throwError, Observable } from 'rxjs'; +import { EditorService } from '../../services/editor/editor.service'; +import { ConfigService } from '../../services/config/config.service'; +import { QuestionService } from '../../services/question/question.service'; +import { config } from 'projects/questionset-editor-library/src/lib/components/asset-browser/asset-browser.data'; +import { ToasterService } from '../../services/toaster/toaster.service'; + +@Component({ + selector: 'lib-assets-browser', + templateUrl: './assets-browser.component.html', + styleUrls: ['./assets-browser.component.scss'] +}) +export class AssetsBrowserComponent implements OnInit, OnChanges, OnDestroy { + @ViewChild('editor') public editorRef: ElementRef; + @Output() videoDataOutput = new EventEmitter(); + @Output() editorDataOutput = new EventEmitter(); + @Input() editorDataInput: any; + @Input() videoShow; + @Input() assetType; + @Input() showAssetPicker; + @Output() assetBrowserEmitter = new EventEmitter(); + @Output() modalDismissEmitter = new EventEmitter(); + @ViewChild('modal') private modal; + myAssets = []; + allAssets = []; + selectedAsset = {}; + loading = false; + isClosable = true; + assetConfig: any = {}; + acceptAssetType: any; + initialized = false; + selectedAssetId: string; + showAddButton: boolean; + showErrorMsg: boolean; + errorMsg: string; + query: string; + showAssetUploadModal: boolean; + assetFormValid = false; + selectast: string; + myast: string; + allast: string; + emptySearchMessage: string; + chooseOrDragAst: string; + astSize: string; + astSizeType: string; + acceptedFileType: string; + + public assetData = {}; + public assetFile: any; + public formData: any; + public mediaobj; + public assetsCount: any; + public editorInstance: any; + public editorConfig: any; + public isAssetBrowserReadOnly = false; + public assetProxyUrl: any; + public initialFormConfig: any; + public formConfig: any; + public termsAndCondition: any; + public assetName: any; + public searchMyInput = ''; + public searchAllInput: any; + public assetUploadLoader = false; + constructor(private editorService: EditorService, public configService: ConfigService, + private questionService: QuestionService, public toasterService: ToasterService) { } + + ngOnInit() { + this.assetProxyUrl = _.get(this.editorService.editorConfig, 'config.assetProxyUrl') || _.get(this.configService.urlConFig, 'URLS.assetProxyUrl'); + this.initialFormConfig = _.get(config, 'uploadIconFormConfig'); + this.formConfig = _.get(config, 'uploadIconFormConfig'); + this.termsAndCondition = _.get(this.configService.labelConfig, 'termsAndConditions.001'); + this.assetConfig = this.editorService.editorConfig.config.assetConfig; + this.initialized = true; + this.selectast = this.configService.labelConfig?.lbl?.selectAsset[this.assetType]; + this.emptySearchMessage = _.get(this.configService.labelConfig?.emptySearchMessage[this.assetType]); + this.myast = this.configService.labelConfig?.lbl?.myAssets[this.assetType]; + this.allast = this.configService.labelConfig?.lbl?.allAssets[this.assetType]; + this.chooseOrDragAst = this.configService.labelConfig?.lbl?.chooseOrDragAsset[this.assetType]; + this.astSize = this.assetConfig[this.assetType].size; + this.astSizeType = this.assetConfig[this.assetType].sizeType; + this.acceptedFileType = this.assetConfig[this.assetType].accepted; + this.acceptAssetType = this.getAcceptType(this.assetConfig[this.assetType].accepted, this.assetType); + this.editorConfig = { + toolbar: ['heading', '|', 'bold', '|', 'italic', '|', 'underline', '|', 'BulletedList', '|', 'alignment', + '|', 'insertTable', '|', 'numberedList', '|', 'fontSize', '|', 'subscript', '|', 'superscript', '|', + 'MathText', '|', 'specialCharacters', '|' + ], + fontSize: { + options: [ + 'eight', + 'ten', + 'twelve', + 'fourteen', + 'sixteen', + 'eighteen', + 'twenty', + 'twentytwo', + 'twentyfour', + 'twentysix', + 'twentyeight', + 'thirty', + 'thirtysix' + ] + }, + image: { + resizeUnit: '%', + resizeOptions: [{ + name: 'resizeImage:25', + value: '25', + icon: 'small', + className: 'resize-25' + }, + { + name: 'resizeImage:50', + value: '50', + icon: 'medium', + className: 'resize-50' + }, + { + name: 'resizeImage:75', + value: '75', + icon: 'large', + className: 'resize-75' + }, + { + name: 'resizeImage:100', + value: '100', + icon: 'full', + className: 'resize-100' + }, + { + name: 'resizeImage:original', + value: null, + icon: 'original', + className: 'resize-original' + }], + toolbar: ['imageStyle:alignLeft', 'imageStyle:alignCenter', 'imageStyle:alignRight', '|', + 'resizeImage:25', 'resizeImage:50', 'resizeImage:75', 'resizeImage:100', 'resizeImage:original'], + styles: ['full', 'alignLeft', 'alignRight', 'alignCenter'] + }, + isReadOnly: false, + removePlugins: ['ImageCaption', 'mathtype', 'ChemType', 'ImageResizeHandles'] + }; + } + + ngOnChanges() { + if (this.videoShow) { + this.showAssetPicker = true; + this.selectAsset(undefined); + } + } + + getAcceptType(typeList, type) { + const acceptTypeList = typeList.split(', '); + const result = []; + _.forEach(acceptTypeList, (content) => { + result.push(`${type}/${content}`); + }); + return result.toString(); + } + + dismissAssetPicker() { + this.showAssetPicker = false; + if(this.assetType=='video') { + this.videoShow=false; + this.videoDataOutput.emit(false); + } else if(this.assetType == 'image') { + this.showAssetPicker = false; + this.modalDismissEmitter.emit({}); + } + } + + selectAsset(data) { + if (data) { + this.showAddButton = true; + this.selectedAssetId = data.identifier; + this.selectedAsset = data; + } else { + this.showAddButton = false; + this.selectedAssetId = ''; + this.selectedAsset = {}; + } + } + + getMyAssets(offset, query?, search?) { + this.assetsCount = 0; + if (!search) { + this.searchMyInput = ''; + if(this.assetType == 'video') { + this.selectAsset(undefined); + } + } + if (offset === 0) { + this.myAssets.length = 0; + } + let req; + req = { + filters: { + mediaType: [this.assetType], + createdBy: _.get(this.editorService.editorConfig, 'context.user.id') + }, + offset + }; + if (query) { + req.query = query; + } + this.questionService.getAssetMedia(req).pipe(catchError(err => { + let errInfo; + if (this.assetType == 'image') { + errInfo = { errorMsg: _.get(this.configService.labelConfig, 'messages.error.022') }; + } else if (this.assetType == 'video') { + errInfo = { errorMsg: _.get(this.configService.labelConfig, 'messages.error.023')}; + } + return throwError(this.editorService.apiErrorHandling(err, errInfo)); + })).subscribe((res) => { + this.assetsCount = res.result.count; + _.map(res.result.content, (item) => { + if (item.downloadUrl) { + this.myAssets.push(item); + } + }); + }); + } + + getAllAssets(offset, query?, search?) { + this.assetsCount = 0; + if (!search) { + this.searchAllInput = ''; + } + if (offset === 0) { + this.allAssets.length = 0; + } + let req; + req = { + filters: { + mediaType: [this.assetType] + }, + offset + }; + if (query) { + req.query = query; + } + this.questionService.getAssetMedia(req).pipe(catchError(err => { + let errInfo; + if (this.assetType == 'image') { + errInfo = { errorMsg: _.get(this.configService.labelConfig, 'messages.error.022') }; + } else if (this.assetType == 'video') { + errInfo = { errorMsg: _.get(this.configService.labelConfig, 'messages.error.023') }; + } + return throwError(this.editorService.apiErrorHandling(err, errInfo)); + })).subscribe((res) => { + this.assetsCount = res.result.count; + _.map(res.result.content, (item) => { + if (item.downloadUrl) { + this.allAssets.push(item); + } + }) + }); + } + + /** + * function to lazy load my assets + */ + lazyloadMyAssets() { + const offset = this.myAssets.length; + this.getMyAssets(offset, this.query, true); + } + + // search feature for images + searchAsset(event, type) { + if (event === 'clearInput' && type === 'myAssets') { + this.query = ''; + this.searchMyInput = ''; + } else if (event === 'clearInput' && type === 'allAssets') { + this.query = ''; + this.searchAllInput = ''; + } else { + this.query = event.target.value; + } + if (type === 'myAssets') { + this.getMyAssets(0, this.query, true); + } else { + this.getAllAssets(0, this.query, true); + } + } + + addAssetInEditor(videoModal?, assetUrl?, assetId?, assetName?) { + if (this.assetType == 'image'){ + const src = this.getMediaOriginURL(assetUrl); + const baseUrl = _.get(this.editorService.editorConfig, 'context.host') || document.location.origin; + this.mediaobj = { + id: assetId, + type: 'image', + src, + baseUrl + }; + this.editorInstance.model.change(writer => { + const imageElement = writer.createElement('image', { + src, + alt: assetName, + 'data-asset-variable': assetId + }); + this.editorInstance.model.insertContent(imageElement, this.editorInstance.model.document.selection); + }); + this.showAssetPicker = false; + this.showAssetUploadModal = false; + } else if (this.assetType == 'video') { + const videoData: any = _.cloneDeep(this.selectedAsset); + videoData.src = this.getMediaOriginURL(videoData.downloadUrl); + videoData.thumbnail = (videoData.thumbnail) && this.getMediaOriginURL(videoData.thumbnail); + this.showAssetPicker = false; + this.videoDataOutput.emit(videoData); + if (videoModal) { + videoModal.deny(); + } + } + } + + getMediaOriginURL(src) { + const replaceText = this.assetProxyUrl; + const cloudStorageUrls = _.compact(_.get(this.editorService.editorConfig, 'context.cloudStorageUrls') || []); + _.forEach(cloudStorageUrls, url => { + if (src.indexOf(url) !== -1) { + src = src.replace(url, replaceText); + } + }); + return src; + } + + /** + * function to lazy load all images + */ + lazyloadAllAssets() { + const offset = this.allAssets.length; + this.getAllAssets(offset, this.query, true); + } + + openAssetUploadModal() { + this.showAssetUploadModal = true; + this.resetFormData(); + } + + resetFormData() { + this.showErrorMsg = false; + this.formData = null; + this.formConfig = this.initialFormConfig; + this.assetUploadLoader = false; + this.assetFormValid = false; + this.loading = false; + this.isClosable = true; + } + + dismissAssetUploadModal() { + if (this.isClosable) { + this.showAssetUploadModal = false; + } + } + + initiateAssetUploadModal() { + this.showAssetPicker = false; + this.showAssetUploadModal = true; + this.loading = false; + this.isClosable = true; + } + + public isEditorReadOnly(state) { + this.editorInstance.isReadOnly = state; + this.isAssetBrowserReadOnly = state; + } + + uploadAsset(event) { + const file = event.target.files[0]; + this.assetName = file.name; + const reader = new FileReader(); + this.formData = new FormData(); + this.formData.append('file', file); + const fileType = file.type; + const fileName = file.name.split('.').slice(0, -1).join('.'); + const fileSize = file.size / 1024 / 1024; + if (fileType.split('/')[0] === this.assetType) { + this.showErrorMsg = false; + if (fileSize > this.assetConfig[this.assetType].size) { + this.showErrorMsg = true; + this.errorMsg = _.get(this.configService.labelConfig, 'messages.error.021') + + this.assetConfig[this.assetType].size + this.assetConfig[this.assetType].sizeType; + this.resetFormConfig(); + } else { + this.errorMsg = ''; + this.showErrorMsg = false; + reader.readAsDataURL(file); + } + } else { + this.showErrorMsg = true; + this.errorMsg = _.get(this.configService.labelConfig?.chooseFileMsg[this.assetType]); + } if (!this.showErrorMsg) { + this.assetUploadLoader = true; + this.assetFormValid = true; + this.assetData = this.generateAssetCreateRequest(fileName, fileType, this.assetType); + this.populateFormData(this.assetData); + } + } + + generateAssetCreateRequest(fileName, fileType, mediaType) { + return { + name: fileName, + mediaType, + mimeType: fileType, + createdBy: _.get(this.editorService.editorConfig, 'context.user.id'), + creator: _.get(this.editorService.editorConfig, 'context.user.fullName'), + channel: _.get(this.editorService.editorConfig, 'context.channel') + }; + } + + populateFormData(formData) { + const formvalue = _.cloneDeep(this.formConfig); + this.formConfig = null; + _.forEach(formvalue, (formFieldCategory) => { + formFieldCategory.default = formData[formFieldCategory.code]; + }); + this.formConfig = formvalue; + } + + resetFormConfig() { + this.assetUploadLoader = false; + this.assetFormValid = false; + this.formConfig = this.initialFormConfig; + } + + onStatusChanges(event) { + if (event.isValid && this.assetUploadLoader) { + this.assetFormValid = true; + } else { + this.assetFormValid = false; + } + } + + valueChanges(event) { + this.assetData = _.merge({}, this.assetData, event); + } + + dismissPops(modal) { + this.dismissAssetPicker(); + modal.deny(); + } + + uploadAndUseAsset(modal) { + this.isClosable = false; + this.loading = true; + this.showErrorMsg = false; + this.assetFormValid = false; + if (!this.showErrorMsg) { + this.questionService.createMediaAsset({ asset: this.assetData }).pipe(catchError(err => { + this.loading = false; + this.isClosable = true; + this.assetFormValid = true; + let errInfo; + if(this.assetType === 'video') { + errInfo = { errorMsg: _.get(this.configService.labelConfig, 'messages.error.025') }; + } else if(this.assetType === 'image') { + errInfo = { errorMsg: _.get(this.configService.labelConfig, 'messages.error.019') }; + } + return throwError(this.editorService.apiErrorHandling(err, errInfo)); + })).subscribe((res) => { + const contentId = res.result.node_id; + const request = { + content: { + fileName: this.assetName + } + }; + this.questionService.generatePreSignedUrl(request, contentId).pipe(catchError(err => { + let errInfo; + errInfo = { errorMsg: _.get(this.configService.labelConfig, 'messages.error.026') }; + this.loading = false; + this.isClosable = true; + this.assetFormValid = true; + return throwError(this.editorService.apiErrorHandling(err, errInfo)); + })).subscribe((response) => { + const signedURL = response.result.pre_signed_url; + let blobConfig = { + processData: false, + contentType: 'Asset' + }; + blobConfig = this.editorService.appendCloudStorageHeaders(blobConfig); + this.uploadToBlob(signedURL, this.assetFile, blobConfig).subscribe(() => { + const fileURL = signedURL.split('?')[0]; + if (this.assetType === 'video') { + this.updateContentWithURL(fileURL, this.assetFile.type, contentId, modal); + } else if (this.assetType ==='image') { + const data = new FormData(); + data.append('fileUrl', fileURL); + data.append('mimeType', _.get(this.assetFile, 'type')); + const config1 = { + enctype: 'multipart/form-data', + processData: false, + contentType: false, + cache: false + }; + const uploadMediaConfig = { + data, + param: config1 + }; + this.questionService.uploadMedia(uploadMediaConfig, contentId).pipe(catchError(err => { + const errInfo = { errorMsg: _.get(this.configService.labelConfig, 'messages.error.019') }; + this.isClosable = true; + this.loading = false; + this.assetFormValid = true; + return throwError(this.editorService.apiErrorHandling(err, errInfo)); + })).subscribe((res) => { + this.addAssetInEditor(res.result.content_url, res.result.node_id); + this.showAssetUploadModal = false; + this.dismissPops(modal); + }) + } + }) + }) + }) + } + } + + updateContentWithURL(fileURL, mimeType, contentId, modal?) { + const data = new FormData(); + data.append('fileUrl', fileURL); + data.append('mimeType', mimeType); + const conf = { + enctype: 'multipart/form-data', + processData: false, + contentType: false, + cache: false + }; + const option = { + data, + param: config + }; + this.questionService.uploadMedia(option, contentId).pipe(catchError(err => { + const errInfo = { errorMsg: _.get(this.configService.labelConfig, 'messages.error.027') }; + this.isClosable = true; + this.loading = false; + this.assetFormValid = true; + return throwError(this.editorService.apiErrorHandling(err, errInfo)); + })).subscribe(res => { + // Read upload asset data + this.getUploadAsset(res.result.node_id, modal); + }); + } + + getUploadAsset(assetId, modal?) { + this.questionService.getVideo(assetId).pipe(map((data: any) => data.result.content), catchError(err => { + const errInfo = { errorMsg: _.get(this.configService, 'labelConfig.messages.error.011') }; + this.loading = false; + this.isClosable = true; + this.assetFormValid = true; + return throwError(this.editorService.apiErrorHandling(err, errInfo)); + })).subscribe(res => { + this.toasterService.success(_.get(this.configService, 'labelConfig.messages.success.006')); + this.selectedAsset = res; + this.showAddButton = true; + this.loading = false; + this.isClosable = true; + this.assetFormValid = true; + this.addAssetInEditor(modal); + }); + } + + uploadToBlob(signedURL, file, config): Observable { + return this.questionService.http.put(signedURL, file, config).pipe(catchError(err => { + const errInfo = { errorMsg: _.get(this.configService.labelConfig, 'messages.error.018') }; + this.isClosable = true; + this.loading = false; + this.assetFormValid = true; + return throwError(this.editorService.apiErrorHandling(err, errInfo)); + }), map(data => data)); + } + + ngOnDestroy() { + if (this.modal && this.modal.deny) { + this.modal.deny(); + } + } +} \ No newline at end of file diff --git a/projects/questionset-editor-library/src/lib/questionset-editor-library.module.ts b/projects/questionset-editor-library/src/lib/questionset-editor-library.module.ts index e2f5303e..b77cdc46 100644 --- a/projects/questionset-editor-library/src/lib/questionset-editor-library.module.ts +++ b/projects/questionset-editor-library/src/lib/questionset-editor-library.module.ts @@ -38,6 +38,7 @@ import { ProgressStatusComponent } from './components/progress-status/progress-s import {TermAndConditionComponent} from './components/term-and-condition/term-and-condition.component'; import { QualityParamsModalComponent } from './components/quality-params-modal/quality-params-modal.component'; +import { AssetsBrowserComponent } from './components/assets-browser/assets-browser.component'; @NgModule({ declarations: [ QuestionsetEditorLibraryComponent, @@ -68,7 +69,8 @@ import { QualityParamsModalComponent } from './components/quality-params-modal/q PlainTreeComponent, ProgressStatusComponent, TermAndConditionComponent, - QualityParamsModalComponent + QualityParamsModalComponent, + AssetsBrowserComponent, ], imports: [CommonModule, FormsModule, ReactiveFormsModule.withConfig({callSetDisabledState: 'whenDisabledForLegacyCode'}), RouterModule.forChild([]), SuiModule, CommonFormElementsModule, InfiniteScrollModule, HttpClientModule, ResourceLibraryModule, A11yModule], diff --git a/projects/questionset-editor-library/src/lib/services/config/label.config.json b/projects/questionset-editor-library/src/lib/services/config/label.config.json index 29e13cd2..5eb298df 100644 --- a/projects/questionset-editor-library/src/lib/services/config/label.config.json +++ b/projects/questionset-editor-library/src/lib/services/config/label.config.json @@ -77,7 +77,7 @@ "answers":"Answers", "answersRequired":"Answer is required", "answersPopupText":"Please provide an answer for the question. Check preview to understand how it would look.", - "selectImage":"Select Image", + "selectImage":"Select Image", "myImages":"My Images", "allImage":"All Image", "uploadAndUse":"Upload and Use", @@ -91,9 +91,28 @@ "copyRightsAndLicense":"Copyright & License", "dropChooseFile":"Drop or choose file to upload before entering the details", "charactersLeft":"Characters left:", + "myAssets": { + "image": "My Images", + "video": "My Video(s)" + }, + "allAssets": { + "image": "All Image", + "video": "All Video(s)" + }, + "selectAsset": { + "image":"Select Image", + "video":"Select Video" + }, + "chooseOrDragAsset": { + "image": "Choose or drag and drop your image here", + "video": "Choose or drag and drop your video here" + }, "myVideos":"My Video(s)", "allVideos":"All Video(s)", "selectVideo":"Select Video", + "myAudios": "My Audio(s)", + "allAudios":"All Audio(s)", + "selectAudio":"Select Audio", "searchPlaceholder":"Search...", "addAnImage":"Add an image", "name":"Name", @@ -247,6 +266,14 @@ "termsAndConditions": { "001": "I understand and confirm that all resources and assets created through the content editor or uploaded on the platform shall be available for free and public use without limitations on the platform (web portal, applications and any other end user interface that the platform would enable) and will be licensed under terms & conditions and policy guidelines of the platform. In doing so, the copyright and license of the original author is not infringed." }, + "emptySearchMessage": { + "image": "No images found, please try searching for something else", + "video": "No videos found, please try searching for something else" + }, + "chooseFileMsg": { + "image": "Please choose an image file", + "video": "Please choose a video file" + }, "messages": { "error": { "001": "Something went wrong, Please try later",
{{assetsCount}}
{{errorMsg}}
{{termsAndCondition}}