	//############################################################################################
	// ### Class C_Document

	const DocReadingDTListMenu = [
				{
					header: ''
				},
				{
						img: 'SubFW/bmp/setup_1_blue.png',
						text: 'Grid properties...',
						action: function(e, selector) { IdcDocReadingDT.Properties (); }
					}
				];

	var IdcDocumentTagsCBMenu = null;
	var IdcDocReadingDT 		= null;

	class C_Document
	{
		constructor ()
		{
			this.Mode  				= -1;
			this.Initialized 		= false;
			this.Type				= "";
			this.Folder				= "";
			this.Filename			= "";
			this.CallbackFct 		= "";
			this.OKCallbackFct 		= "";
			this.ErrorCallbackFct 	= "";
			this.CurrentStatusID	= -1;

			this.ExtID 				= -1;
			this.ExtType 			= -1;
			this.DocType 			= -1;
			this.DocID   			= -1;

			this.ActionID 			= -1;

			let nbItems = $('.c_document').length;
			let tmp;

			if ( nbItems == 0 )
			{
				tmp = '';

				tmp += '<div id="IdcDocReadCertificate"  class="modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" style="z-index: 2000 !important;">';
				tmp += 		'<div class="modal-dialog modal-dialog-centered modal-lg" role="document" style="resize: true;">';
				tmp += 			'<div class="modal-content">';
							
				tmp += 				'<div class="modal-header p-3 pb-3 pt-3 border-bottom bg-light">';
				tmp += 					'<h5 id="IdcDocReadCertificate_DlgCaption" class="fw-bold mb-0"></h5>';
				tmp += 					'<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" onclick="$(\'#IdcDocReadCertificate\').modal(\'hide\')"></button>';
				tmp += 				'</div>';
										
				tmp += 				'<div class="modal-body w-100 pb-0">';
				tmp += 					'<div class="container p-0 m-0">';
					
				tmp += 						'<div class="row m-0 p-0 w-100 overflow-auto" style="min-height: 500px !important; max-height: 500px !important;">';
				tmp += 							'<div id="IdcDocReadingDTContainer"></div>';						
				tmp += 						'</div>';

				tmp += 					'</div>';
				tmp += 					'<div class="modal-footer mt-3">';
				tmp += 						'<button class="ximeo_button">';
				tmp += 							'<img src="'+G_ServerFolder+'/eoQUAL/SubFW/bmp/validate_white.png" class="float-start me-2" style="width: 18px; vertical-align: middle;">';
				tmp += 							'<span data-langkey="Validate">Validate</span>';
				tmp += 						'</button>';
				tmp += 						'<button class="ximeo_button" onclick="$(\'#IdcDocReadCertificate\').modal(\'hide\')">';
				tmp += 							'<img src="'+G_ServerFolder+'/eoQUAL/SubFW/bmp/close_white.png" class="float-start me-2" style="width: 18px; vertical-align: middle;">';
				tmp += 							'<span data-langkey="Cancel">Cancel</span>';
				tmp += 						'</button>';
				tmp += 					'</div>';
				tmp += 				'</div>';
				tmp += 			'</div>';
				tmp += 		'</div>';
				tmp += 	'</div>';

				$('body').append (tmp);


				const docReadCertificate = document.getElementById ( 'IdcDocReadCertificate' );
				docReadCertificate.addEventListener ('shown.bs.modal', function () { console.log ("IdcDocReadCertificate shown !!!"); IdcDocReadingDT.Refresh (); } );
				let docFormatAction = this.DocFormatAction.bind ( this );
				IdcDocReadingDT = new C_DataTable ();
				IdcDocReadingDT.DataSrcType		= 0;
				IdcDocReadingDT.Ident 			= 'IdcDocReadingDT';
				IdcDocReadingDT.Container 		= 'IdcDocReadingDTContainer';
				IdcDocReadingDT.DataSrc 		=  G_ServerFolder+'/eoQUAL/SubFW/database/document/GetDTDocumentReader.php';
				IdcDocReadingDT.DataFct			= this.ReadDocumentGetData.bind ( this );
				IdcDocReadingDT.SetColReorder 	( true );
				IdcDocReadingDT.OnSelectChanged	( this.ReadDocumentDTSelectChanged.bind ( this ) );
				IdcDocReadingDT.AddColumn ( 'id',						'id',	 				0, false,  0,  50,   false, '', 			'' );
				IdcDocReadingDT.AddColumn ( Translate('Action'),		'action_id',			1, true,   1, '30%', true, 	'', 			'', docFormatAction );
				IdcDocReadingDT.AddColumn ( Translate('Fullname'),		'fullname',				1, true,   2, '30%', true, 	'', 			'' );
				IdcDocReadingDT.AddColumn ( Translate('Job'),			'job',	 				1, true,   3, '20%', true,  '', 			'' );
				IdcDocReadingDT.AddColumn ( Translate('Institution'),	'institution',			1, true,   4, '20%', true,  '', 			'' );
				IdcDocReadingDT.AddColumn ( Translate('Department'),	'department',			1, true,   5, '20%', true,  '', 			'' );
				IdcDocReadingDT.AddColumn ( Translate('Date'),			'action_at_fmt',		1, true,   6, '20%', true,  'text-center', 	'' );
				IdcDocReadingDT.SetColumnFilter (	'action_id','<select class="form-select form-select-sm" id ="DocReadingActionFilter"><option value="0" data-langkey="Reading"></option><option value="1" data-langkey="Validate"><option value="2" data-langkey="Writing"></option></option></select>' );
				IdcDocReadingDT.SetColumnFilter (  'fullname', '<div class="m-0 p-0 ps-0 pe-1 pb-2"><input id="IdcDocReadingFullnameFilter" class="form-control pt-0 pb-0" oninput="IdcDocReadingDT.Refresh()" type="text" placeholder="'+Translate("Staff member")+'"></div>' );
				IdcDocReadingDT.SetColumnFilter (  'read_at_fmt', '<div class="form-check"><input class="form-check-input" type="checkbox" value="" id="flexCheckDefault"><label class="form-check-label" for="flexCheckDefault">Non lu</label></div>' );
				IdcDocReadingDT.LoadUserCfg ( G_USE_ID );
				IdcDocReadingDT.Create ();
				context.attach ( '#IdcDocReadingDT', DocReadingDTListMenu );
				IdcDocReadingDT.SetRowToSelect('first_row');
			}

			this.Ident 	= "Idc_C_DocumentDlg_" + nbItems;

			console.log ( "Ident : " + this.Ident );


			tmp = '';
			tmp += '<div id="'+this.Ident+'"  class="c_document modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" style="z-index: 10000 !important;">';
			tmp += 		'<div class="modal-dialog modal-dialog-centered modal-lg" role="document" style="resize: true;">';
			tmp += 			'<div class="modal-content">';
							
			tmp += 				'<div class="modal-header p-3 pb-3 pt-3 border-bottom bg-light">';
			tmp += 					'<h5 id="'+this.Ident+'_DlgCaption" class="fw-bold mb-0"></h5>';
			tmp += 					'<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" onclick="$(\'#'+this.Ident+'\').modal(\'hide\')"></button>';
			tmp += 				'</div>';
										
			tmp += 				'<div class="modal-body w-100 pb-0">';
			tmp += 					'<div class="container w-100 p-0 m-0">';

			tmp += 						'<div class="row w-100 h-100 m-0 p-0">';

			tmp += 							'<div class="col w-100 h-100 m-0 p-0">';
					
			tmp += 								'<div class="row m-0 p-0 w-100">';
			tmp += 									'<div class="col p-0 col-md-auto">';
			tmp += 										'<div class="m-0 p-0 pt-1 ps-0 pe-1 mb-2" data-langkey="Status :" ></div>';
			tmp += 										'<div class="m-0 p-0 pt-1 ps-0 pe-1 mb-2" data-langkey="Date :" ></div>';
			tmp += 										'<div class="m-0 p-0 pt-1 ps-0 pe-1 mb-2" data-langkey="Valid until :"></div>';
			tmp += 										'<div id="'+this.Ident+'_NameRowLabel" class="collapse m-0 p-0 pt-3 pb-2 w-100">';
			tmp += 											'<div class="m-0 p-0 pt-2 ps-0 pe-1 mb-2" data-langkey="Document name :"></div>';
			tmp +=										'</div>';
			tmp += 										'<div class="m-0 p-0 pt-1 ps-0 pe-1 mb-2" data-langkey="Version label :"></div>';
			tmp += 										'<div class="m-0 p-0 pt-3 ps-0 pe-1 mb-2" data-langkey="Tag auto-audit :"></div>';
			tmp += 									'</div>';
			tmp += 									'<div class="col m-0 p-0">';
			tmp +=										'<div class="row m-0 p-0 pb-3">';
			tmp +=											'<div class="col-auto m-0 p-0">';
			tmp +=												'<select class="form-select m-0 p-0 ps-2" id="'+this.Ident+'_Status" style="min-width: 200px;">';
			tmp +=												'</select>';
			tmp +=											'</div>';
			tmp +=										'</div>';
			tmp +=										'<div class="row m-0 p-0">';
			tmp +=											'<div class="col-auto m-0 p-0">';
			tmp += 												'<input type="date" id="'+this.Ident+'_Date" class="form-control form-control-sm m-0 p-0 ps-2 mb-1" autocomplete="off" placeholder="jj/mm/aaaa" />';
			tmp +=											'</div>';
			tmp +=										'</div>';
			tmp +=										'<div class="row m-0 p-0">';
			tmp +=											'<div class="col-auto m-0 p-0">';
			tmp += 												'<input type="date" id="'+this.Ident+'_ValidUntil" class="form-control form-control-sm m-0 p-0 ps-2 mb-1" autocomplete="off" placeholder="jj/mm/aaaa" />';
			tmp +=											'</div>';
			tmp +=										'</div>';
			tmp += 										'<div id="'+this.Ident+'_NameRowInput" class="collapse m-0 p-0 pt-3 pb-2 w-100">';
			tmp += 											'<input type="text" id="'+this.Ident+'_Name" class="form-control form-control-sm m-0 p-0 ps-2 mb-1">';
			tmp +=										'</div>';
			tmp += 										'<input type="text" id="'+this.Ident+'_Label" class="form-control form-control-sm m-0 p-0 ps-2 mb-1">';
			tmp +=										'<div class="row m-0 p-0 pt-1">';
			tmp +=											'<div id="'+this.Ident+'_TagsContainer" class="m-0 p-0 mb-1"></div>';
			tmp +=										'</div>';		
								
			tmp += 									'</div>';
			tmp += 								'</div>';
						
			tmp += 								'<div class="row m-0 p-0 w-100">';
			tmp += 									'<div class="col m-0 p-0">';
			tmp += 										'<label for="'+this.Ident+'_Comment" class="form-label m-0 p-0" data-langkey="Comment :"></label>';
			tmp += 										'<textarea class="form-control m-0 p-0 ps-2 mb-1" id="'+this.Ident+'_Comment" rows="5"></textarea>';
			tmp += 									'</div>';
			tmp += 								'</div>';

			tmp += 								'<div class="row m-0 p-0 pt-2 w-100" id="'+this.Ident+'_PreviousDocumentRow">';
			tmp += 									'<div class="col m-0 p-0">';
			tmp += 										'<input class="form-check-input" type="checkbox" checked id="'+this.Ident+'_PreviousDocumentCB">';
			tmp += 										'<label class="form-check-label ps-2" for="'+this.Ident+'_PreviousDocumentCB">Source précédente</label>';
			tmp += 									'</div>';
			tmp += 								'</div>';

			tmp += 								'<div class="row-auto m-0 p-0 w-100" id="'+this.Ident+'_DocumentRow">';
			tmp +=									'<fieldset class="ximeo_fieldset mb-1 mt-2 m-0">';
			tmp +=										'<legend class="ximeo_fieldset" data-langkey="Document :"></legend>';

			tmp +=										'<div class="row m-0 p-0 pb-3 border-bottom">';
			tmp +=											'<div class="col-auto m-0 p-0 ps-0 pe-2" data-langkey="Document type :">';
			tmp +=											'</div>';
			tmp +=											'<div class="col m-0 p-0 pe-1">';
			tmp +=												'<select class="form-select m-0 p-0 ps-1" id="'+this.Ident+'_DocumentType" style="min-width: 200px;">';
			tmp +=												'</select>';
			tmp +=											'</div>';
			tmp +=										'</div>';
			
			tmp += 										'<div id="'+this.Ident+'_ExternLinkRow" class="collapse m-0 p-0 pt-3 pb-2 w-100">';
			tmp += 											'<div class="row m-0 p-0 w-100">';
			tmp += 												'<div class="m-0 p-0 pt-1 ps-0 pe-1 mb-2" data-langkey="Extern document :"></div>';
			tmp += 												'<input type="text" id="'+this.Ident+'_ExternLink" class="form-control form-control-sm m-0 p-0 ps-2 mb-1" data-langkey_placeholder="Link to document">';
			tmp += 											'</div>';
			tmp += 										'</div>';

			tmp += 										'<div id="'+this.Ident+'_FileRow" class="collapse m-0 p-0 pt-3 pb-2 w-100">';
			tmp += 											'<div class="row m-0 p-0 pt-1 w-100">';
			tmp += 												'<div class="m-0 p-0">';
			tmp += 													'<label for="'+this.Ident+'_File" class="form-label m-0 p-0 pb-2" data-langkey="File :"></label>';
			tmp += 													'<input class="form-control m-0" type="file" id="'+this.Ident+'_File" readonly>';
			tmp += 												'</div>';
			tmp += 											'</div>';
			tmp += 										'</div>';

			tmp += 										'<div id="'+this.Ident+'_ProgressRow" class="collapse m-0 p-0 pt-3 pb-2 w-100">';
			tmp += 											'<div class="row m-0 p-0 pt-3 pb-2 w-100">';
			tmp +=												'<div class="col">';
			tmp +=													'<button id="'+this.Ident+'_Abort" class="btn btn-primary text-center pt-0 pb-0 ps-2 pe-2" style="background-color: #2F83B0" >';
			tmp +=	 													'<img src="'+G_ServerFolder+'/eoQUAL/SubFW/bmp/validate_white.png" class="imgclickable float-start me-2" style="width: 18px; vertical-align: middle;">';
			tmp += 														'<span data-langkey="Abort">Abort</span>';
			tmp += 													'</button>';
			tmp +=												'</div>';
			tmp +=												'<div class="col">';
			tmp +=													'<progress id="'+this.Ident+'_Progress">';
			tmp += 													'</progress>';
			tmp +=												'</div>';
			tmp +=												'<div class="col">';
			tmp +=													'<output id="'+this.Ident+'_Output">';
			tmp += 													'</output>';
			tmp +=												'</div>';
			tmp +=											'</div>';
			tmp +=										'</div>';
			tmp +=									'</fieldset>';
			tmp +=								'</div>';	// row
					
			tmp += 							'</div>';	// col

			tmp +=							'<div class="col-auto m-0 p-0 ps-2 ms-3 border-start">';

			tmp +=								'<div class="d-flex flex-column h-100 w-100 m-0 p-0">';

			tmp +=									'<div class="row m-0 p-0 pb-2 ps-2 border-bottom">';
			tmp +=										'<div class="m-0 p-0 fw-bold"><span id="IdcDocActionMandatoryTitle"></span></div>';
			tmp +=									'</div>';
			tmp += 									'<div class="row flex-grow-1 m-0 p-0 w-100 overflow-auto" style="min-height: 0px; !important">';
			tmp += 										'<div class="m-0 p-0 pt-2" id="'+this.Ident+'_Tree"></div>';						
			tmp +=	 								'</div>';
			tmp +=								'</div>';

			tmp +=							'</div>';

			tmp += 						'</div>';	// row

			tmp += 					'</div>';	// container

			tmp += 					'<div class="modal-footer mt-3">';
			tmp += 						'<button class="ximeo_button" onclick="C_DocumentValidate(\''+this.Ident+'\')">';
			tmp += 							'<img src="'+G_ServerFolder+'/eoQUAL/SubFW/bmp/validate_white.png" class="float-start me-2" style="width: 18px; vertical-align: middle;">';
			tmp += 							'<span data-langkey="Validate">Validate</span>';
			tmp += 						'</button>';
			tmp += 						'<button class="ximeo_button" onclick="$(\'#'+this.Ident+'\').modal(\'hide\')">';
			tmp += 							'<img src="'+G_ServerFolder+'/eoQUAL/SubFW/bmp/close_white.png" class="float-start me-2" style="width: 18px; vertical-align: middle;">';
			tmp += 							'<span data-langkey="Cancel">Cancel</span>';
			tmp += 						'</button>';
			tmp += 					'</div>';	// modal-footer

			tmp += 				'</div>';	// modal-body
			tmp += 			'</div>';		// modal-content
			tmp += 		'</div>';			// modal-dialog
			tmp += 	'</div>';				// c_document

					
			$('body').append (tmp);

			let previousDocumentCBChanged = this.PreviousDocumentCBChanged.bind ( this );
			const docPreviousCB = document.getElementById ( this.Ident+'_PreviousDocumentCB' );
			docPreviousCB.addEventListener ( 'change', previousDocumentCBChanged );

			IdcDocumentTagsCBMenu = new C_CheckboxMenu ( this.Ident+'_TagsContainer', this.Ident+'_TagsCB', Translate("Click here to select tags") );
			// IdcExamsListTagsCBMenu.CallbackFct = ExamsListTagsChanged;

			let statusChanged = this.StatusChanged.bind ( this );
			document.getElementById ( this.Ident + "_Status").addEventListener ( "change", statusChanged );

			let documentTypeChanged = this.DocumentTypeChanged.bind (this);
			document.getElementById ( this.Ident + "_DocumentType" ).addEventListener ( "change", documentTypeChanged );

			FillStatusList 		( this.Ident + '_Status', 'document' );
			FillDocumentType	( this.Ident + '_DocumentType', 1 );

			$( '#'+this.Ident ).data ( 'CDObj', this );
		}

		PreviousDocumentCBChanged ()
		{
			console.log ( "PreviousDocumentCBChanged...");

			let docPreviousCB = document.getElementById ( this.Ident+'_PreviousDocumentCB' );

			console.log ( "checked :  " + docPreviousCB.checked );

			const div = document.getElementById ( this.Ident+'_DocumentRow' );

			if ( this.Mode == 2 && docPreviousCB.checked )	// New version
			{
				div.querySelectorAll ('input, button, textarea,select').forEach ( el =>el.disabled=true);
				div.style.pointerEvents = 'none';
				div.style.opacity = '0.5';
			}
			else
			{
				div.querySelectorAll ('input, button, textarea,select').forEach ( el =>el.disabled=false);
				div.style.pointerEvents = 'auto';
				div.style.opacity = '1';
			}
		}

		DocFormatAction ( data )
		{
			let ret = '';

			switch ( data )
			{
				case "0":	ret = 'Validation';		break;
				case "2":	ret = 'Rédaction';		break;
				case "1":	ret = 'Lecture';		break;
			}

			return ret;
		}

		ReadDocumentGetData ( d )
		{
			console.log ( "ReadDocumentGetData...");

			let doc_id = $('#IdcDocReadCertificate').data ( "doc_id" );
			console.log ( " doc_id : " + doc_id );

			let fullname = $('#IdcDocReadingFullnameFilter').val ();
			console.log ( " fullname : " + fullname );

			d.doc_id 	= doc_id;
			d.fullname	= fullname;

			return $.extend( {}, d );
		}

		ReadDocumentDTSelectChanged ()
		{
			console.log ( "ReadDocumentDTSelectChanged..." );
		}

		DocumentTypeChanged ()
		{
			console.log ( "DocumentTypeChanged..." );

			let docType = $('#'+this.Ident+'_DocumentType').val ();
			// let docType 	= this.DocType;


			console.log ( " docType : " + docType );

			switch ( docType )
			{
				case "0": // External document
					$( '#' + this.Ident + '_ExternLinkRow' ).addClass ( 'show' );
					$( '#' + this.Ident + '_FileRow' ).removeClass ( 'show' );
					break;
				
				case "1": // PDF document
					$( '#' + this.Ident + '_ExternLinkRow' ).removeClass ( 'show' );
					$( '#' + this.Ident + '_FileRow' ).addClass ( 'show' );
					$('#'+this.Ident+'_File').attr('accept', '.pdf');
					break;

				case "2": // Word document
					$( '#' + this.Ident + '_ExternLinkRow' ).removeClass ( 'show' );
					$( '#' + this.Ident + '_FileRow' ).addClass ( 'show' );
					$('#'+this.Ident+'_File').attr('accept', '.docx');
					break;

				case "3": // Excel document
					$( '#' + this.Ident + '_ExternLinkRow' ).removeClass ( 'show' );
					$( '#' + this.Ident + '_FileRow' ).addClass ( 'show' );
					$('#'+this.Ident+'_File').attr('accept', '.xlsx');
					break;
			}
		}

		InitTags ( type )
		{
			console.log ( "InitTags ("+type+")..." );

			let cbElem = IdcDocumentTagsCBMenu;

			cbElem.ClearAll ();

			let lastSeparator = "";
		
			var xhra= getxhr();
			
			xhra.onloadend = function f()
			{
				if ( xhra.readyState == 4 && xhra.status == 200 )  
				{
					let reponse		= clean(xhra.responseXML.documentElement);
					let tags	 	= reponse.getElementsByTagName ( 'tag' );
				
					let lastType = '';

					for ( let i=0; i<tags.length; i++ )
					{
						let id			= tags.item (i).getAttribute ( "id" 	);
						let name		= tags.item (i).getAttribute ( "name" 	);
						let type		= tags.item (i).getAttribute ( "type" 	);

						if ( lastType != type )
						{
							cbElem.AddTextSeparator ( type );
							lastType = type;
						}
																	
						cbElem.AddItem ( -1, id, name );
					}
				}
			};

			let url = G_ServerFolder + "/eoQUAL/SubFW/database/common/get_bquaad_tag.php?document_scope="+type;
			// let url = G_ServerFolder + "/eoQUAL/SubFW/database/common/get_bquaad_tag.php";
			xhra.open ('GET', url, false );
			xhra.send ();
		}

		FillReadDefaultMandatory ( ext_id, ext_type, doc_type, action_id )
		{
			console.log ( "FillReadDefaultMandatory ( "+ext_id+", "+ext_type+", "+doc_type+", "+action_id+" )..." );
			
			let treeIdent = this.Ident + "_Tree";

			TreeViewUncheckAll ( treeIdent );
			
			$.post (
				G_ServerFolder+"/eoQUAL/SubFW/database/document/get_action_mandatory_from_default.php",
				{
					action_id:  action_id,		// 0 : Validate, 1 : Reading, 2 : Writing
					ext_id: 	ext_id,
					ext_type: 	ext_type,
					doc_type: 	doc_type
				},
					function (data, status)
					{		
						console.log ( " data.status : " + data.status );

						for (let i=0; i<data.results.length; i++ )
						{
							TreeViewCheckItem ( treeIdent, data.results [i] );
						}
					}
				);
		}

		FillReadMandatory ( doc_id, action_id )
		{
			console.log ( "FillReadMandatory ( "+doc_id+" )..." );
			
			let treeIdent = this.Ident + "_Tree";

			TreeViewUncheckAll ( treeIdent );
			
			$.post (
					G_ServerFolder+"/eoQUAL/SubFW/database/document/get_action_mandatory.php",
					{
						doc_id: 	doc_id,
						action_id:  action_id,		// 0 : Validate, 1 : Reading, 2 : Writing
					},
					function (data, status)
					{		
						for ( let i=0; i<data.results.length; i++ )
						{
							TreeViewCheckItem ( treeIdent, data.results [i].staff_member_id );
						}
					}
			);
		}

		

		Show ( mode, data )		// mode 0 : Add, mode 1 : Edit, mode 2 : Add version
		{
			console.log ( "Show...");

			console.log ( "Ident : " + this.Ident );
			console.log ( "ID : " + data.ID );
			console.log ( "Extension : " + data.Extension );

			document.getElementById ( this.Ident +'_File' ).value = "";

			if ( this.Initialized == false )
				this.Initialized = true;

			this.InitTags ( data.DocType );

			let cbElem = IdcDocumentTagsCBMenu;

			let loadData = this.LoadData.bind ( this );
			
			switch ( mode )
			{
				case 0: 	// Add
					this.Mode = 0;

					$( '#' + this.Ident + '_NameRowLabel' ).removeClass ( 'collapse' );
					$( '#' + this.Ident + '_NameRowInput' ).removeClass ( 'collapse' );
					$( '#' + this.Ident + '_DocumentRow'  ).removeClass ( 'collapse' );
					$( '#' + this.Ident + '_PreviousDocumentRow'  ).addClass ( 'collapse' );

					$( '#' + this.Ident ).data ('ext_id', data.ExtID );
					$( '#' + this.Ident + '_Name' ).val ( '' );
					$( '#' + this.Ident + '_Label' ).val ( '' );
					$( '#' + this.Ident + '_Comment' ).val ( '' );
					$( '#' + this.Ident + '_Date' ).val ( GetCurrentDate () );
					$( '#' + this.Ident + '_ValidUntil' ).val ( '' );

					$( '#' + this.Ident + '_Status' ).val ( 10 );	// Draft
					cbElem.UnselectAll ();
					break;

				case 1: 	// Edit
					this.Mode = 1;

					$( '#' + this.Ident + '_NameRowLabel' ).removeClass ( 'collapse' );
					$( '#' + this.Ident + '_NameRowInput' ).removeClass ( 'collapse' );
					$( '#' + this.Ident + '_DocumentRow'  ).addClass ( 'collapse' );
					$( '#' + this.Ident + '_PreviousDocumentRow'  ).addClass ( 'collapse' );

					$( '#' + this.Ident ).data ( 'id', data.ID );
					loadData ( data.DocType, data.ID );
					break;

				case 2: 	// Add version
					this.Mode = 2;

					$( '#' + this.Ident + '_NameRowLabel' ).addClass ( 'collapse' );
					$( '#' + this.Ident + '_NameRowInput' ).addClass ( 'collapse' );
					$( '#' + this.Ident + '_DocumentRow'  ).removeClass ( 'collapse' );
					$( '#' + this.Ident + '_PreviousDocumentRow'  ).removeClass ( 'collapse' );

					$( '#' + this.Ident ).data ( 'id', data.ID );
					$( '#' + this.Ident ).data ('ext_id', data.ExtID );
					$( '#' + this.Ident + '_Name' ).val ( '' );
					$( '#' + this.Ident + '_Label' ).val ( '' );
					$( '#' + this.Ident + '_Comment' ).val ( '' );
					$( '#' + this.Ident + '_Date' ).val ( GetCurrentDate () );
					$( '#' + this.Ident + '_ValidUntil' ).val ( '' );
					$( '#' + this.Ident + '_Status' ).val ( 10 );	// Draft
					cbElem.UnselectAll ();
					break;
			}

			this.PreviousDocumentCBChanged ();
			

			

			// TEST 

			console.log ( " ext_id : " + data.ExtID );
			console.log ( " doc_id : " + data.ID );
			console.log ( " Doc Type : " + data.DocType );
			console.log ( " Ext Type : " + data.ExtType );

			

			this.ExtID 				= data.ExtID;
			this.ExtType 			= data.ExtType;
			this.DocType 			= data.DocType;
			this.DocID   			= data.ID;
			this.Extension 			= data.Extension;

			this.DocumentTypeChanged ();
			this.StatusChanged ();

		
			$( '#' + this.Ident+'_DlgCaption' ).text ( data.Caption );
			this.Type  				= data.DocType;
			this.Folder				= data.Folder;
			this.CallbackFct 		= (data.CallbackFct != undefined)? 		data.CallbackFct 		: "";
			this.OKCallbackFct 		= (data.OKCallbackFct != undefined)? 	data.OKCallbackFct 		: "";
			this.ErrorCallbackFct 	= (data.ErrorCallbackFct != undefined)? data.ErrorCallbackFct 	: "";

			$('#'+this.Ident+'').modal('show');
		}

		Add ( data )
		{
			this.Show ( 0, data );
		}

		Edit ( data )
		{
			this.Show ( 1, data );
		}

		AddVersion ( data )
		{
			this.Show ( 2, data );
		}

		OnLoadDataOK ( data )
		{
			let cbElem = IdcDocumentTagsCBMenu;

			$( '#' + this.Ident + '_Name' ).val ( data.name );
			$( '#' + this.Ident + '_Label' ).val ( data.label );
			$( '#' + this.Ident + '_Comment' ).val ( data.comment );
			$( '#' + this.Ident + '_Status' ).val ( data.status_id );
			$( '#' + this.Ident + '_Date' ).val ( DICOMDate2StdDate(data.create_date) );
			$( '#' + this.Ident + '_ValidUntil' ).val ( DICOMDate2StdDate(data.valid_until_date) );
			/*
			let tagsArray = data.bquaad_tag_list.split(',');
			cbElem.SelectElementIdent2 ( tagsArray );
			*/
			if ( data.bquaad_tag_list != null )
			{
				let tagsArray = data.bquaad_tag_list.split(',');
				cbElem.SelectElementIdent2 ( tagsArray );
			}

			this.CurrentStatusID = data.status_id;
		}

		LoadData ( type, id )
		{
			let onLoadDataOK = this.OnLoadDataOK.bind(this);
			var request = $.ajax ({
        		url: 		G_ServerFolder + "/eoQUAL/SubFW/database/common/db_form_document_load.php",
        		type: 		"post",
        		dataType: 	"json",
        		data: 		{id: id}
    			}
    		)
			.done ( onLoadDataOK )
    		.fail ();
		}


		Close ()
		{
			$('#'+this.Ident+'').modal('hide');
		}

		Validate ()
		{
			// let file 		= $('#'+this.Ident +'_File').get(0).files[0];

			let files 	= document.getElementById ( this.Ident +'_File' ).files;
			let docType = $('#'+this.Ident+'_DocumentType').val ();
			/*
			switch ( docType )
			{
				case "1": // PDF document
					MsgWarning ( "Un fichier PDF doit être sélectionné !!!" );
					break;
			}
			*/

			
			let uploadFile  						= this.UploadFile.bind(this);
			let newVersionBasedOnPreviousDocument 	= this.NewVersionBasedOnPreviousDocument.bind ( this );
			let saveForm							= this.SaveForm.bind(this);

			switch ( this.Mode )
			{
				case 0:  	// Add
					if ( files.length == 0 )	// New file
					{
						if ( docType == "1" )
						{
							MsgWarning ( "Un fichier PDF doit être sélectionné !!!" );
							return;
						}
						uploadFile ( this.Folder, null, docType );
					}
					else
						uploadFile ( this.Folder, files [0] );
					break;

				case 1:  	// Edit
					{
						let newStatus = $('#'+this.Ident+"_Status").val ();

						console.log ( " CurrentStatus : " + this.CurrentStatusID );
						console.log ( " newStatus : " + newStatus );

						let doc_id = $( '#' + this.Ident ).data ( 'id' );
						console.log ( " doc_id : " + doc_id );

						let extension = this.Extension;

						switch ( this.CurrentStatusID )
						{
							case '10': 		// Draft
								{
									switch ( newStatus )
									{
										case '14': 	// Published
											MsgYesNo ( Translate("Do you really want to publish this document ?"), function () 
											{
												if ( extension == "pdf" )
												{
													MsgWarning ( Translate("The document is now published.") );
													saveForm ();
												}
												else
												{
													WaitingStart ( Translate("Publication in progress...") );
													$.post (
														"./SubFW/html/OnlyOfficeConvert.php",
														{
															doc_id: 	doc_id
														},
														function (data)
														{		
															console.log ( " data.status : " + data.status );

															WaitingStop ();
														
															if ( data.status == "OK" )
															{
																MsgWarning ( Translate("The document is now published.") );
																saveForm ();
															}
															else
																MsgWarning ( "Erreur durant la publication du document !!!" );
														}
													);	
												}		
											} );
											break;

										case '11': 	// Pending approval
											MsgYesNo ( Translate("Would you like to request validation of this document ?"), function () 
											{
												if ( extension == "pdf" )
												{
													MsgWarning ( Translate("The document is now awaiting validation.") );
													saveForm ();
												}
												else
												{
													WaitingStart ( Translate("PDF conversion in progress...") );
													$.post (
														"./SubFW/html/OnlyOfficeConvert.php",
														{
															doc_id: 	doc_id
														},
														function (data)
														{		
															WaitingStop ();
														
															if ( data.status == "OK" )
															{
																MsgWarning ( Translate("The document is now awaiting validation.") );
																saveForm ();
															}
															else
																MsgWarning ( "Erreur durant la conversion du document !!!" );
														}
													);
												}
											} );
											break;

										case '12': 	// Approved
											MsgYesNo ( Translate("Would you like to mark this document as approved ?"), function () 
											{
												if ( extension == "pdf" )
												{
													MsgWarning ( Translate("The document is now approved.") );
													saveForm ();
												}
												else
												{
													WaitingStart ( Translate("PDF conversion in progress...") );
													$.post (
														"./SubFW/html/OnlyOfficeConvert.php",
														{
															doc_id: 	doc_id
														},
														function (data)
														{		
															WaitingStop ();
														
															if ( data.status == "OK" )
															{
																MsgWarning ( Translate("The document is now approved.") );
																saveForm ();
															}
															else
																MsgWarning ( "Erreur durant la conversion du document !!!" );
														}
													);
												}
											} );	
											break;

										default:
											console.log ( "Default 2");
											saveForm ();
											break;
									}
									
								}
								break;

							default:
								console.log ( "Default 1");
								saveForm ();
								break;
						}

						
					}
					break;

				case 2:  	// New version
					let docPreviousCB = document.getElementById ( this.Ident+'_PreviousDocumentCB' );
					if ( docPreviousCB.checked )
					{
						console.log ( "Use previous version..." );
						newVersionBasedOnPreviousDocument ();
					}
					else
						uploadFile ( this.Folder, files [0] );
					break;
			}
		}

		SaveForm ( uploaded_filename )
		{
			console.log ( "SaveForm..." );

			let saveFail 	= this.SaveFail.bind(this);
			let saveOK 		= this.SaveOK.bind(this);

			let cbMenu = IdcDocumentTagsCBMenu;
			let type  		= this.Type;
			let status 		= $( '#' + this.Ident + '_Status' ).val ();
			let date 		= $( '#' + this.Ident + '_Date' ).val ();
			let validUntil	= $( '#' + this.Ident + '_ValidUntil' ).val ();
			let name		= $( '#' + this.Ident + '_Name' ).val ();
			let label		= $( '#' + this.Ident + '_Label' ).val ();
			let comment		= $( '#' + this.Ident + '_Comment' ).val ();
			let extern_link	= $( '#' + this.Ident + '_ExternLink' ).val ();
			let tags 		= cbMenu.GetSelection2 ().toString();
			let filename  	= this.Filename;

			console.log ( " name : " + name );
			console.log ( " status : " + status );
			console.log ( " extern_link : " + extern_link );

			if ( this.CallbackFct != "" )
			{
				console.log ( "Callback...");

				let values = { 	'Date': 				date,
								'ValidUntil': 			validUntil,
								'Name': 				name,
								'Label': 				label,
								'Comment': 				comment,
								'Filename':	 			filename,
								'UploadedFilename':	 	uploaded_filename,
								'Tags': 				tags	};

				this.CallbackFct ( values );
			}
			else
			{
				let data 		= {};
				let toProcess 	= false;

				switch ( this.Mode )
				{
					case 0:  	// Add
						{
							let id = $('#' + this.Ident ).data ('ext_id');

							// let row_id = '1';
							let row_id = id;

    						data [id+'_!nativeeditor_status'] 	= 'inserted';
    						data [id+'_documentmode']			= 'newdocument';
    						data [id+'_ext_id']					= id;
    						data [id+'_document_type']			= type;
    						data [id+'_status_id']				= status;
    						data [id+'_name']					= name;
    						data [id+'_create_date']			= date;
    						data [id+'_valid_until_date']		= validUntil;
    						data [id+'_label']					= label;
    						data [id+'_comment']				= comment;
    						data [id+'_uploaded_by']			= G_USE_ID;
    						data [id+'_revision']				= 1;
    						data [id+'_devicedocumentfile_r_0']	= filename;
    						data [id+'_devicedocumentfile_s_0'] = uploaded_filename;
    						data [id+'_bquaad_tag']				= tags;
    						data ['ids']						= row_id;

    						toProcess = true;
    					}
    					break;

    				case 1: 	// Edit
    					{
							let id = $('#' + this.Ident ).data ('id');

    						data [id+'_!nativeeditor_status'] 	= 'updated';
    						data [id+'_create_date']			= date;
    						data [id+'_valid_until_date']		= validUntil;
    						data [id+'_status_id']				= status;
    						data [id+'_name']					= name;
    						data [id+'_label']					= label;
    						data [id+'_comment']				= comment;
    						data [id+'_extern_link']			= extern_link;
    						data [id+'_bquaad_tag']				= tags;

    						data ['ids']						= id;

    						toProcess = true;
    					}
    					break;

    				case 2:  	// Add version
						{
							let ext_id 	= $('#' + this.Ident ).data ('ext_id');
							let id 		= $('#' + this.Ident ).data ('id');

							data [id+'_!nativeeditor_status'] 	= 'inserted';
							data [id+'_document_type']			= type;
							data [id+'_ext_id']					= ext_id;
							// data [id+'_name']					= name;
							data [id+'_label']					= label;
							data [id+'_comment']				= comment;
							data [id+'_uploaded_by']			= G_USE_ID;
							data [id+'_status_id']				= status;
							data [id+'_create_date']			= date;
							data [id+'_valid_until_date']		= validUntil;
							data [id+'_extern_link']			= extern_link;
							data [id+'_devicedocumentfile_r_0']	= filename;
    						data [id+'_devicedocumentfile_s_0'] = uploaded_filename;
    						data [id+'_documentparent']			= id;			
    						data [id+'_bquaad_tag']				= tags;
	   						data ['ids']						= id;

    						toProcess = true;
    					}
    					break;
    			}
    			if ( toProcess == true )
    			{
					var request = $.ajax ({
        				url: G_ServerFolder + "/eoQUAL/SubFW/database/common/document.php",
        				type: "post",
        				dataType: "json",
        				data: data
    					}
    				)
    				.done ( saveOK )
    				.fail ( saveFail );
    			}
			}
			
			// $('#'+this.Ident+'').modal('hide');
		}

		SaveOK ( data )
		{
			console.log ( "SaveOK..." );
			console.log ( " data.tid : " + data.tid );

			console.log ( "this.ActionID : " + this.ActionID );

			let action_id = this.ActionID;

			// TEST
    		let selItems 	= TreeViewGetSelectedItems   ( this.Ident + "_Tree" );		// Staff_IDs selected
    		let unselItems 	= TreeViewGetUnselectedItems ( this.Ident + "_Tree" );		// Staff_IDs unselected
					
			let toAdd 		= JSON.stringify ( selItems   );
			let toRemove	= JSON.stringify ( unselItems );
			
			$.post (
				G_ServerFolder+"/eoQUAL/SubFW/database/document/save_action_mandatory.php",
				{
					doc_id: 	data.tid,
					action_id:  action_id,
					toadd: 		toAdd,
					toremove: 	toRemove
				},
				function (data, status)
				{		
				}
			);
								
    		// END TEST

			this.Close ();
			
			if ( this.OKCallbackFct != "" )
				this.OKCallbackFct ( data );
		}

		SaveFail ()
		{
			if ( this.ErrorCallbackFct != "" )
				this.ErrorCallbackFct ();
		}

		NewVersionBasedOnPreviousDocument ()
		{
			console.log ( "NewVersionBasedOnPreviousDocument..." );
			let ext_id 	= $('#' + this.Ident ).data ('ext_id');
			let id 		= $('#' + this.Ident ).data ('id');

			console.log ( " ext_id : " + ext_id );
			console.log ( " id : " + id );

			let saveForm = this.SaveForm.bind ( this );

			$.post (
				"./SubFW/database/document/prepare_new_version.php",
				{
					doc_id:  id
				},
				function (data, status)
				{		
					console.log ( " data.status : " + data.status );
					console.log ( " data.filename : " + data.filename );

					saveForm ( data.filename );
				}
			);
		}

		UploadEnded ( uploaded_filename )
		{
			$( '#' + this.Ident + '_ProgressRow' ).removeClass ( 'show' );

			this.SaveForm ( uploaded_filename );
		}


		UploadError ()
		{
		}

		UploadFile ( folder, fileToUpload, docType )
		{
			$( '#' + this.Ident + '_ProgressRow' ).addClass ( 'show' );

			// Test =========================================================================

			// ==============================================================================
			
			// this.Filename = fileToUpload.name;

			let uploadError = this.UploadError.bind(this);
			let uploadEnded = this.UploadEnded.bind(this);

  			const progressBar 	= document.getElementById ( this.Ident+"_Progress" );
  			const log 			= document.getElementById ( this.Ident+"_Output" );
  			const abortButton 	= document.getElementById ( this.Ident+"_Abort" );

   			const xhr = new XMLHttpRequest();
   			xhr.timeout 		= 20000; // 20 seconds
   			xhr.responseType	= "text";
   			
   			xhr.onreadystatechange = function() 
   			{
   				if ( xhr.readyState==4 )
    			{
    				if ( xhr.status == 200 )
    				{
    					let res = JSON.parse ( xhr.responseText ).result;

        				if ( res == 'OK' )
        				{
        					log.textContent = "Upload finished.";
        					uploadEnded ( JSON.parse ( xhr.responseText ).filename );
        				}
        				else
        				{
        					log.textContent = "Upload error.";
        					uploadError ();
        				}
        			}
        			else
        			{
        				log.textContent = "Upload error.";
        				uploadError ();
        			}
    			}
			};
			

   			
   			// Link abort button
   			abortButton.addEventListener (
     			"click",
      			() => {
        			xhr.abort();
      			},
      			{ once: true },
    		);

    		// When the upload starts, we display the progress bar
    		xhr.upload.addEventListener("loadstart", (event) => {
      			progressBar.classList.add("visible");
      			progressBar.value = 0;
      			progressBar.max = event.total;
      			log.textContent = "Uploading (0%)…";
      			abortButton.disabled = false;
    		});

    		// Each time a progress event is received, we update the bar
    		xhr.upload.addEventListener("progress", (event) => {
      			progressBar.value = event.loaded;
      			log.textContent = `Uploading (${(
        		(event.loaded / event.total) *
        		100
      			).toFixed(2)}%)…`;
    		});

    		/*
    		xhr.upload.addEventListener("loadend", (event) => {
    			progressBar.classList.remove("visible");
      			if (event.loaded !== 0) 
      			{
        			log.textContent = "Upload finished.";
        			this.UploadEnded ();
      			}
      			abortButton.disabled = true;
    		});

    		xhr.upload.addEventListener("error", (event) => {
    				log.textContent = "Upload finished.";
        			this.UploadError ();      			
    		});
    		*/

    		function errorAction(event) 
    		{
      			progressBar.classList.remove("visible");
      			log.textContent = `Upload failed: ${event.type}`;

      			this.UploadError ();
    		}
    		// xhr.upload.addEventListener("error", errorAction);
    		xhr.upload.addEventListener("abort", errorAction);
    		xhr.upload.addEventListener("timeout", errorAction);
    		

    		// Build the payload
    		const fileData = new FormData();
    		/*
    		fileData.append ( "file", fileToUpload );
    		fileData.append ( 'folder', folder );
    		this.Filename = fileToUpload.name;
    		*/

    		if ( fileToUpload != null )
    		{
    			fileData.append ( "file", fileToUpload );
    			fileData.append ( 'folder', folder );
    			this.Filename = fileToUpload.name;

    			xhr.open("POST", G_ServerFolder + "/eoQUAL/SubFW/html/UploadFile.php", true);
    			xhr.send(fileData);
    		}
    		else 	// New document docx or xlsx
    		{
    			// =================================================================================
    			switch ( docType )
    			{
    				case "2": 	// DOCX
						CreateDOCX ().then ( file => {
							fileData.append( "file", file);
							fileData.append ( 'folder', folder );

							xhr.open("POST", G_ServerFolder + "/eoQUAL/SubFW/html/UploadFile.php", true);
    						xhr.send(fileData);
						});
						break;

					case "3": 	// XLSX
						CreateXLSX ().then ( file => {
							fileData.append( "file", file);
							fileData.append ( 'folder', folder );

							xhr.open("POST", G_ServerFolder + "/eoQUAL/SubFW/html/UploadFile.php", true);
    						xhr.send(fileData);
						});
						break;
				}
			}
			

    		// =================================================================================
			/*
    		xhr.open("POST", G_ServerFolder + "/eoQUAL/SubFW/html/UploadFile.php", true);

    		// Note that the event listener must be set before sending (as it is a preflighted request)
    		xhr.send(fileData);
    		*/
  		}

  		StatusChanged ()
		{
			console.log ( "StatusChanged...");

			let newStatus = $('#'+this.Ident+"_Status").val ();

			console.log ( " CurrentStatus : " + this.CurrentStatusID );
			console.log ( " newStatus : " + newStatus );

			// Test only
			// $('#'+this.Ident+'_File').attr('accept', '.docx');

			/*
			$('#myFileInput').on('change', function() {
  				const file = this.files[0];
  				if (file && !file.type.startsWith('image/')) {
    				alert('Seuls les fichiers image sont autorisés.');
    				this.value = ''; // Réinitialise l'input
  				}
				});
			*/

			let ident 		= this.Ident;
			let extID		= this.ExtID;
			let extType 	= this.ExtType;
			let docType 	= this.DocType;
			let docID 		= this.DocID;
			let mode 		= this.Mode;

			console.log ( " mode : " + mode );


			let action_id = -1;

			let status_id 	= $( '#' + this.Ident + '_Status' ).val ();

			switch ( status_id )
			{	
				case "10": 	// Draft
					action_id = 2; 	// Read
					$("#IdcDocActionMandatoryTitle").text ( Translate("Authorized writers") );
					break;

				case "11": 	// Pending approval
					action_id = 0; 	// Validate
					$("#IdcDocActionMandatoryTitle").text ( Translate("Mandatory validation certificate") );
					break;

				case "12": 	// Approved
				case "14":  // Published
					action_id = 1; 	// Read
					$("#IdcDocActionMandatoryTitle").text ( Translate("Mandatory reading certificate") );
					break;
			}

			this.ActionID = action_id;

			let fillReadDefaultMandatory 	= this.FillReadDefaultMandatory.bind ( this );
			let fillReadMandatory 			= this.FillReadMandatory.bind ( this );

			console.log ( " extID : " + extID );
			console.log ( " extType : " + extType );
			
			$.post (
				G_ServerFolder + "/eoQUAL/SubFW/database/common/get_instdep_from_extid.php",
					{
						ext_id: extID,
						type: extType
					},
					function (data, status)
					{		
						console.log ( " data.status : " + data.status );

						for (let i=0; i<data.results.length; i++ )
						{
							console.log ( "results ["+i+"] : " + data.results [i].text );
						}

						let treeIdent = ident + "_Tree";

						$('#'+treeIdent).C_TreeView ( { data: data.results } );

						if ( mode == 0 || mode == 2 )	// Add or Add version
						{
							fillReadDefaultMandatory ( extID, extType, docType, action_id );
						}
						else
						{
							fillReadMandatory ( docID, action_id );
						}	
					}
			);
		}
	}

	function C_DocumentValidate ( ident )
	{
		let cdObj = $('#'+ident).data ('CDObj');

		cdObj.Validate ();
	}


	

	//############################################################################################
	// ### Class C_DocumentDT

	var DT_DocumentDlg = null;

	function CDShortcut ( origine )
	{
		let version = parseInt(origine);
		if ( version > 1 )
			return '<img class=\"C_DocumentDT_Histo imgclickable  pe-2\" title=\"'+Translate ( 'Previous versions' )+'\" src=\"'+G_ServerFolder+'/eoQUAL/SubFW/bmp/counter_back_blue.png\" style=\"height: 18px; width: auto;\"></img><img class=\"C_DocumentDT_AddVersion imgclickable  pe-2\" title=\"'+Translate ( 'Add' )+'\" src=\"'+G_ServerFolder+'/eoQUAL/SubFW/bmp/add_blue.png\" style=\"height: 18px; width: auto;\"></img><img class=\"C_DocumentDT_Edit imgclickable  pe-2\" title=\"'+Translate ( 'Edit' )+'\" src=\"'+G_ServerFolder+'/eoQUAL/SubFW/bmp/edit_blue.png\" style=\"height: 18px; width: auto;\"></img><img class=\"C_DocumentDT_View imgclickable  pe-2\" title=\"'+Translate ( 'View' )+'\" src=\"'+G_ServerFolder+'/eoQUAL/SubFW/bmp/view_blue_48.png\" style=\"height: 18px; width: auto;\"></img><img class=\"C_DocumentDT_ReadingCertificate imgclickable  pe-2\" title=\"'+Translate ( 'Reading certificate' )+'\" src=\"'+G_ServerFolder+'/eoQUAL/SubFW/bmp/user_read_blue.png\" style=\"height: 18px; width: auto;\"></img>';
		else
			return '<img class=\"C_DocumentDT_NoHisto imgclickable  pe-2\" title=\"'+Translate ( 'No previous versions' )+'\" src=\"'+G_ServerFolder+'/eoQUAL/SubFW/bmp/counter_back_gray.png\" style=\"height: 18px; width: auto;\" disable></img><img class=\"C_DocumentDT_AddVersion imgclickable  pe-2\" title=\"'+Translate ( 'Add' )+'\" src=\"'+G_ServerFolder+'/eoQUAL/SubFW/bmp/add_blue.png\" style=\"height: 18px; width: auto;\"></img><img class=\"C_DocumentDT_Edit imgclickable  pe-2\" title=\"'+Translate ( 'Edit' )+'\" src=\"'+G_ServerFolder+'/eoQUAL/SubFW/bmp/edit_blue.png\" style=\"height: 18px; width: auto;\"></img><img class=\"C_DocumentDT_View imgclickable  pe-2\" title=\"'+Translate ( 'View' )+'\" src=\"'+G_ServerFolder+'/eoQUAL/SubFW/bmp/view_blue_48.png\" style=\"height: 18px; width: auto;\"></img><img class=\"C_DocumentDT_ReadingCertificate imgclickable  pe-2\" title=\"'+Translate ( 'Reading certificate' )+'\" src=\"'+G_ServerFolder+'/eoQUAL/SubFW/bmp/user_read_blue.png\" style=\"height: 18px; width: auto;\"></img>';
	}

	class C_DocumentDT
	{
		constructor ( ident )
		{
			if ( DT_DocumentDlg == null )
				DT_DocumentDlg = new C_Document ();

			// External data
			this.Ident				= ident;
			this.OneOnly			= false;
			this.Caption			= "";
			this.Container			= "";
			this.DocType			= "";
			this.ExtType			= "";
			this.ExtID  			= -1;
			this.Extension 			= "";		// pdf, docx, xlsx

			this.Editor				= null;


			// Local data
			this.DocDT 				= null;
			this.Initialized 		= false;
		
			this.DocDT = new C_DataTable ();
			this.DocDT.DataSrcType			= 0;
			this.DocDT.Ident 				= this.Ident +'_DT';
			this.DocDT.Container 			= this.Ident + '_DTContainer';
			this.DocDT.DataSrc 				= G_ServerFolder+'/eoQUAL/SubFW/database/common/GetDTRealDocuments.php';
			this.DocDT.DataFct				= this.DTGetData.bind(this);
			this.DocDT.SetColReorder 	( true );

			// this.DocDT.AddColumn ( 'Shortcuts',				'',		 					0, true,   0, 	 100, false, '', 	'<img class=\"C_DocumentDT_Histo imgclickable  pe-2\" title=\"'+Translate ( 'Previous versions' )+'\" src=\"SubFW/bmp/counter_back_blue.png\" style=\"height: 18px; width: auto;\"></img><img class=\"C_DocumentDT_AddVersion imgclickable  pe-2\" title=\"'+Translate ( 'Add' )+'\" src=\"SubFW/bmp/add_blue.png\" style=\"height: 18px; width: auto;\"></img><img class=\"C_DocumentDT_Edit imgclickable  pe-2\" title=\"'+Translate ( 'Edit' )+'\" src=\"SubFW/bmp/edit_blue.png\" style=\"height: 18px; width: auto;\"></img><img class=\"C_DocumentDT_View imgclickable  pe-2\" title=\"'+Translate ( 'View' )+'\" src=\"SubFW/bmp/view_blue_48.png\" style=\"height: 18px; width: auto;\"></img>' );
			this.DocDT.AddColumn ( Translate('Shortcuts'),	'shortcut',					0, true,   0, 	 140, false, '', 	'', CDShortcut );
			this.DocDT.AddColumn ( 'id',					'id',	 					1, false,  1,  '10%', false, '',	'' );
			this.DocDT.AddColumn ( 'doc_master_id',			'doc_master_id',			1, false,  2,  '10%', false, '',	'' );
			this.DocDT.AddColumn ( 'doc_master_groupid',	'doc_master_groupid',		1, false,  3,  '10%', true,  '', 	'' );
			this.DocDT.AddColumn ( 'status_id',				'status_id',				1, false,  4,  '10%', false,  '', 	'' );
			this.DocDT.AddColumn ( 'extension',				'extension',				1, true,   5,  '10%', false,  '', 	'' );
			this.DocDT.AddColumn ( Translate('Name'),		'name',						1, true,   6,  '10%', true,  '', 	'' );
			this.DocDT.AddColumn ( Translate('Rev.'),		'revision',	 				1, true,   7,  '10%', true,  '',	'' );
			this.DocDT.AddColumn ( Translate('Label'),		'label', 					1, true,   8,  '10%', true,  '', 	'' );
			this.DocDT.AddColumn ( Translate('Date'),		'date',						1, true,   9,  '10%', true,  'dt-center', 	'' );
			this.DocDT.AddColumn ( Translate('Author'),		'author',					1, false, 10,  '10%', true,  '', 	'' );
			this.DocDT.AddColumn ( Translate('Status'),		'status_name',				1, true,  11,  '10%', true,  '', 	'', Translate );
			this.DocDT.AddColumn ( Translate('Comment'),	'comment',					1, false, 12,  '10%', true,  '', 	'' );
			this.DocDT.AddColumn ( Translate('Valid until'),'valid_until_date',			1, true,  13,  '10%', true,  '', 	'' );
		}

		Create ( mode )		// Mode : 0 = couleur application, arrondi, pading 2.   Mode : 1 = couleur gris, pas d'arrondi, padding 0.
		{
			mode = ( mode == undefined )? 0 : mode;
			let tmp = "";

			let onAddDocument 		= this.OnAddDocument.bind (this)
			let onDeleteDocument 	= this.OnDeleteDocument.bind (this)

			let border = '';
			switch ( mode )
			{
				default:
				case 0:
					tmp += '<div id="'+this.Ident+'_Div" class="c_documentdt d-flex flex-column h-100 p-2">';
					tmp += 		'<div class="row m-0">';
					tmp +=			'<div class="ximeo_caption w-100 text-white ps-2 pe-2 pt-2 pb-2">';
					break;
			
				case 1:
				{
					tmp += '<div id="'+this.Ident+'_Div" class="c_documentdt d-flex flex-column h-100 p-0 border">';
					tmp += 		'<div class="row m-0">';
					tmp += 				'<div class="w-100 m-0 ps-2 pe-2 pt-1 pb-1 border-bottom ximeo_bg-dark-3 text-white" >';
					break;
				}

				case 2:
				{
					tmp += '<div id="'+this.Ident+'_Div" class="c_documentdt d-flex flex-column h-100 p-0">';
					tmp += 		'<div class="row m-0">';
					tmp += 			'<div class="w-100 m-0 ps-2 pe-2 pt-1 pb-1 border-bottom ximeo_bg-dark-3 text-white rounded-top" >';
					border = 'border-start border-bottom border-end';
					break;
				}
			}

			tmp +=				'<div class="row w-100 m-0 p-0">';
			tmp +=					'<div class="col-auto m-0 p-0">';
			tmp +=						'<span data-langkey="'+this.Caption+'"></span>';
			tmp +=					'</div>';
			tmp +=					'<div class="col m-0 p-0">';
			tmp +=						'<div class="d-flex flex-row-reverse w-100 h-100 m-0 p-0">';
			tmp +=							'<div class="col-md-auto h-100 m-0 p-0">';
			tmp +=								'<img id="'+this.Ident+'_DeleteButton" src="'+G_ServerFolder+'/eoQUAL/SubFW/bmp/trash_white.png" data-langkey_title="Delete" class="imgclickable ximeo_bmp">';
			tmp +=							'</div>';
			tmp +=							'<div class="col-md-auto h-100 m-0 p-0 ps-2 pe-2">';
			tmp +=								'<img id="'+this.Ident+'_AddButton" src="'+G_ServerFolder+'/eoQUAL/SubFW/bmp/add_white.png" data-langkey_title="Add" class="imgclickable ximeo_bmp">';
			tmp +=							'</div>';
			tmp +=						'</div>';
			tmp +=					'</div>';
			tmp +=				'</div>';
			tmp +=			'</div>';
			tmp +=		'</div>';
			tmp +=		'<div class="row flex-grow-1 m-0 '+border+'">';
			tmp +=			'<div id="'+this.Ident+'_DTContainer" class="col w-100 h-100 m-0 p-0 ps-2 pe-2 bg-white">';
			tmp +=			'</div>';
			tmp +=		'</div>';
			tmp +=	'</div>';


			document.getElementById ( this.Container ).innerHTML = tmp;

			document.getElementById ( this.Ident + '_AddButton' 	).addEventListener ( "click", onAddDocument 	);
			document.getElementById ( this.Ident + '_DeleteButton' 	).addEventListener ( "click", onDeleteDocument 	);

			if ( this.OneOnly == true )
				this.DocDT.OnSelectChangedFct	= this.DTSelectChanged.bind(this);

			this.DocDT.Create ();

			let dtProperties = this.DTProperties.bind (this);

			let C_DocumentDTListMenu = [
			{
				header: ''
			},
			{	
				img: G_ServerFolder+'/eoQUAL/SubFW/bmp/setup_1_blue.png',
				text: 'Grid properties...',
				action: function(e, selector) { dtProperties (); }
			}
			];

			context.attach ( '#' + this.DocDT.Ident, C_DocumentDTListMenu );
			this.DocDT.SetRowToSelect('first_row');

			let onHistoDocument 				= this.OnHistoDocument.bind ( this );
			let onAddVersion 					= this.OnAddVersion.bind ( this );
			let onEditDocument 					= this.OnEditDocument.bind ( this );
			let onViewDocument 					= this.OnViewDocument.bind ( this );
			let onReadingCertificateDocument 	= this.OnReadingCertificateDocument.bind ( this );

			$('#'+this.Ident +'_DT'+' tbody').on('click', '.C_DocumentDT_Histo', function () 
			{
				let tr = $(this).closest('tr');
					
				onHistoDocument ( tr );
			} );	

			let ident = this.Ident;
			$('#'+this.Ident +'_DT'+' tbody').on('click', '.C_DocumentDT_AddVersion', function () 
			{
				let row = $(this).closest('tr');
				let id = $('#'+ident +'_DT').DataTable().row( row ).data().id;
					
				onAddVersion ( id );
			} );	

			$('#'+this.Ident +'_DT'+' tbody').on('click', '.C_DocumentDT_Edit', function () 
			{
				let row = $(this).closest('tr');
				let id 			= $('#'+ident +'_DT').DataTable().row( row ).data().id;
				let extension 	= $('#'+ident +'_DT').DataTable().row( row ).data().extension;
					
				onEditDocument ( id, extension );
			} );	

			$('#'+this.Ident +'_DT'+' tbody').on('click', '.C_DocumentDT_View', function () 
			{
				let row = $(this).closest('tr');
				let id 			= $('#'+ident +'_DT').DataTable().row( row ).data().id;
				let label 		= $('#'+ident +'_DT').DataTable().row( row ).data().label;
				let name 		= $('#'+ident +'_DT').DataTable().row( row ).data().name;
				let revision	= $('#'+ident +'_DT').DataTable().row( row ).data().revision;
				let status_id	= $('#'+ident +'_DT').DataTable().row( row ).data().status_id;
				let extension	= $('#'+ident +'_DT').DataTable().row( row ).data().extension;			// pdf, docx
					
				onViewDocument ( id, label, name, revision, status_id, extension );
			} );

			$('#'+this.Ident +'_DT'+' tbody').on('click', '.C_DocumentDT_ReadingCertificate', function () 
			{
				let row = $(this).closest('tr');
				let id 			= $('#'+ident +'_DT').DataTable().row( row ).data().id;
				let label 		= $('#'+ident +'_DT').DataTable().row( row ).data().label;
				let name 		= $('#'+ident +'_DT').DataTable().row( row ).data().name;
				let revision	= $('#'+ident +'_DT').DataTable().row( row ).data().revision;
					
				onReadingCertificateDocument ( id, label, name, revision );
			} );	
		}

		DTSelectChanged ( rowsIdx )
		{
			let ident = '#'+this.Ident+"_AddButton";

			if ( this.DocDT.GetRowNumber () > 0 )	
				$( ident ).hide ();
			else
				$( ident ).show ();
		}

		LoadUserCfg ( use_id )
		{
			this.DocDT.LoadUserCfg ( use_id );
		}

		DTProperties ()
		{
			this.DocDT.Properties ();
		}

		DTGetData ( d ) 
		{
			d.ext_id 		= this.ExtID;
			d.doctype		= this.DocType;
			d.versioning	= 0;
					
			return $.extend( {}, d );
		}

	
		FillSubDT ( d ) 
		{
			let onViewHistoDocument 	= this.OnViewHistoDocument.bind ( this );

			let div = $('<div/>')
				.addClass( 'loading' )
				.text( 'Loading...' );

			$.post (
				"SubFW/database/common/get_document_versions.php",
				{
					doc_master_id: d.doc_master_id
				},
				function (data)
				{
					let ret = "";
					ret += "<div class=\"m-2 p-2 border bg-light\">";
					ret += "<div class=\"row m-0 p-2 ps-0 pt-0 fw-bold\">";
					ret += Translate("Previous versions");
					ret += "</div>";
					ret += "<div class=\"row m-0 p-0\">";
					ret += "<table id=\"IdcTable001\" class='SubTable m-0 p-0 border-bottom w-100'>";
					ret += 	"<thead class=\"border-bottom\" style=\"border-color: #067fb8 !important;\">";
					ret += 		"<tr>";
					ret +=			"<th class='border-end' style='width:20px'></th>";
					// ret +=			"<th class='border-end p-0 ps-2 fw-normal' style='width:50px' style=\"display: none;\">ID</th>";
					ret +=			"<th class='border-end p-0 ps-2 fw-bold' style='width:120px'>"+Translate('Status')+"</th>";
					ret +=			"<th class='border-end p-0 ps-2 fw-bold' style='width:40px'>Rev.</th>";
					ret +=			"<th class='border-end p-0 ps-2 fw-bold' style='width:70px'>Date</th>";
					ret +=			"<th class='border-end p-0 ps-2 fw-bold' style='width:100px'>Depuis</th>";
					ret +=			"<th class='border-end p-0 ps-2 fw-bold' style='width:100px'>Jusqu'à</th>";
					ret += 			"<th class='border-end p-0 ps-2 fw-bold' style='width:120px'>Label</th>";
					ret += 			"<th class='border-end p-0 ps-2 fw-bold'>"+Translate('Comment')+"</th>";
					ret += 		"</tr>";
					ret += 	"</thead>";
					ret += 	"<tbody class='SubTable'>";

					let documents = data.results;
					for ( var i=0; i<documents.length; i++ )
					{	
						let revision		= documents[i].revision;

						if ( revision != d.revision )
						{
							let id 				= documents[i].doc_id;
							let status_id		= documents[i].status_id;
							let status_name		= Translate(documents[i].status_name);
							let label			= documents[i].label;
							let comment			= documents[i].comment;
							let creation_date	= documents[i].creation_date;
							let begdate			= documents[i].status_begin_date;
							let enddate			= documents[i].status_end_date;
							let revision		= documents[i].revision;
							let extension		= documents[i].extension;

							console.log ( "id : " + id + "   extension : " + extension );
					
							ret +=		"<tr>";
							if ( status_id == "2" || status_id== "14")
								ret +=			"<td class='border-end'><img class=\"C_DocumentDT_Sub_Histo imgclickable  pe-2\" title='"+Translate('View')+"' src=\"SubFW/bmp/view_blue_48.png\" style=\"height: 18px; width: auto;\" data-id=\""+id+"\" data-label=\""+label+"\" data-status_id=\""+status_id+"\" data-revision=\""+revision+"\" data-extension=\""+extension+"\"></img></td>";
							else
								ret +=			"<td class='border-end'></td>";
							ret +=			"<td class='border-end p-0 ps-2' style=\"display: none;\">"+id+"</td>";
							ret +=			"<td class='border-end p-0 ps-2'>"+status_name+"</td>";
							ret +=			"<td class='border-end p-0 ps-2 pe-2 text-end'>"+revision+"</td>";
							ret +=			"<td class='border-end p-0 ps-2'>"+creation_date+"</td>";
							ret +=			"<td class='border-end p-0 ps-2'>"+begdate+"</td>";
							ret +=			"<td class='border-end p-0 ps-2'>"+enddate+"</td>";
							ret +=			"<td class='border-end p-0 ps-2'>"+label+"</td>";
							ret +=			"<td class='border-end p-0 ps-2'>"+comment+"</td>";
																	
							ret +=		"</tr>";
						}
					}
					
					ret +=		"</tbody>";
					ret +=	"</table>";
					ret += "</div>";
					ret += "</div>";
				
					div
						.html( ret )
						.removeClass( 'loading' );

					let elements = document.getElementsByClassName ( 'C_DocumentDT_Sub_Histo' );
					for ( let i=0; i<elements.length; i++ )
						elements [i].addEventListener ( "click", function (event) { onViewHistoDocument (event); } 	);
				}
			);

			return div;
		}

		Refresh ()
		{
			this.DocDT.Refresh ();
		}

		// ##########################################################################""
		// ### Add document

		AddDocumentOKCallback ( data )
		{
			this.DocDT.Refresh ();
			this.DocDT.SetRowToSelect ( 'id', data.tid );
		}

		AddDocumentErrorCallback ( data )
		{
		}

		OnAddDocument ()
		{
			let data = {};
			data.DocType			= this.DocType;
			data.ExtType			= this.ExtType;
			data.Caption			= Translate ( "New document" );
			data.Folder				= this.DocType;
			data.ExtID  			= this.ExtID;
			data.OKCallbackFct 		= this.AddDocumentOKCallback.bind(this);
			data.ErrorCallbackFct 	= this.AddDocumentErrorCallback.bind(this);

			DT_DocumentDlg.Add ( data );
		}


		// ##########################################################################""
		// ### Delete document

		OnDeleteDocument ()
		{
			let data = {};
			data.RequestURL		= G_ServerFolder + "/eoQUAL/SubFW/database/common/delete_document.php";
			data.RequestData	= "id";
			data.DTColIdent		= "id";
			data.NoSelectedMsg 	= Translate ( "No document selected !!!" );
			data.ConfirmMsg 	= Translate ( "Delete selected document ?" );
			data.ErrorMsg 		= Translate ( "Unable to delete document !!!" );

			this.DocDT.DeleteSelectedRow ( data );
		}

	
		// ##########################################################################""
		// ### Version histo

		OnHistoDocument ( tr )
		{
			let row = $('#'+this.Ident+'_DT').DataTable ().row ( tr );
 
			if ( row.child.isShown() ) 
			{
				row.child.hide ();
				tr.removeClass ( 'shown' );
			} 
			else 
			{
				row.child ( this.FillSubDT ( row.data() ) ).show ();
				tr.addClass ( 'shown' );
			}
		}

	
		// ##########################################################################""
		// ### Edit document

		OnEditDocument ( id, extension )
		{
			console.log ( "C_DocumentDT::OnEditDocument...");
			console.log ( " id : " + id );
			console.log ( " extension : " + extension );
			console.log ( " ExtID : " + this.ExtID );
			console.log ( " DocType : " + this.DocType );
			console.log ( " ExtType : " + this.ExtType );

			let data = {};
			data.DocType			= this.DocType;
			data.ExtType			= this.ExtType;
			data.Caption			= Translate ( "Edit document" );
			data.ExtID  			= this.ExtID;
			data.ID  				= id;
			data.Extension			= extension;
			data.OKCallbackFct 		= this.AddDocumentOKCallback.bind(this);
			data.ErrorCallbackFct 	= this.AddDocumentErrorCallback.bind(this);
		
			DT_DocumentDlg.Edit ( data );
		}

	
		// ##########################################################################""
		// ### View document

		OnDocumentReadingValidation ()
		{
			console.log ( "OnDocumentReadingValidation..." );
			console.log ( " DocID : " + this.DocID );

			let doc_id = this.DocID;

			$.post (
				"./SubFW/database/document/save_read_status.php",
				{
					doc_id: 	doc_id
				},
					function (data, status)
					{		
						console.log ( " data.status : " + data.status );

						for (let i=0; i<data.results.length; i++ )
						{
							console.log ( " results ["+i+"] : " + data.results [i].doc_id + " / " + data.results [i].staff_member_id );
						}
					}
				);
		}

		OnViewDocument ( id, label, name, revision, status_id, extension )
		{
			console.log ( "OnViewDocument...");
			console.log ( " status_id : " + status_id );
			console.log ( " id : " + id );
			this.DocID = id;
			let caption = name + " - revision " + revision;

			if ( status_id == 10 && (extension=="docx" || extension=="xlsx") )	// Draft
			{
				if ( this.Editor != null )
					this.Editor ( id );
			}
			else
			{
				let url = G_ServerAddress + G_ServerFolder + "/PDFViewer/eoQUALPDFViewer.php?docid="+id;

				let readingValidation = this.OnDocumentReadingValidation.bind ( this );
				DocumentViewerShow ( caption, null, url, null, readingValidation );
			}
		}

		// ##########################################################################""
		// ### Reading certificate document

		OnReadingCertificateDocument ( id, label, name, revision )
		{
			console.log ( "OnReadingCertificateDocument..." );
			console.log ( " doc_id : " + id );
			console.log ( " Type : " + this.DocType );

			let type = this.DocType;

			let caption = name + " - revision " + revision;
			// let url = G_ServerAddress + G_ServerFolder + "/PDFViewer/eoQUALPDFViewer.php?docid="+id;
			// DocumentViewerShow ( caption, null, url );

			$('#IdcDocReadCertificate_DlgCaption').text ( caption );
			$('#IdcDocReadCertificate').data ( "doc_id", id );
			$('#IdcDocReadCertificate').modal ( 'show' );
			/*
			$.post (
					"./SubFW/database/common/get_instdep_from_doc.php",
					{
						doc_id: id,
						type: type
					},
					function (data, status)
					{		
						console.log ( " data.status : " + data.status );

						for (let i=0; i<data.results.length; i++ )
						{
							console.log ( "results ["+i+"] : " + data.results [i].text );
						}
					}
			);
			*/
		}

	
		// ##########################################################################""
		// ### Add version

		OnAddVersion ( id )
		{
			let data = {};
			data.DocType		= this.DocType;
			data.ExtType		= this.ExtType;
			data.Folder			= this.DocType;
			data.Caption		= Translate ( "New version" );
			data.ID  			= id;
			data.ExtID  		= this.ExtID;
			data.OKCallbackFct  = this.AddDocumentOKCallback.bind(this);
		
			DT_DocumentDlg.AddVersion ( data );
		}

		// ##########################################################################""
		// ### View document from histo

		OnViewHistoDocument ( el )
		{
			let id 			= el.target.getAttribute('data-id');
			let label 		= el.target.getAttribute('data-label');
			let status_id 	= el.target.getAttribute('data-status_id');
			let revision 	= el.target.getAttribute('data-revision');
			let extension	= el.target.getAttribute('data-extension');
			let name 		= "";

			console.log ( " label : " + label );
			console.log ( " extension : " + extension );
			console.log ( " status_id : " + status_id );
			console.log ( " revision : " + revision );

			this.OnViewDocument ( id, label, name, revision, status_id, extension );
		}
	}

