@@ -37,6 +37,31 @@ function isZipMode() {
3737}
3838
3939var redactedMode ;
40+ var canRedact = false ;
41+ var redactedFileExists = false ;
42+
43+ async function checkPermissions ( ) {
44+ let permissionsUrl = queryParams . signedUrls ? queryParams . signedUrls . userPermissions : null ;
45+ if ( ! permissionsUrl && queryParams . siteUrl && queryParams . datasetid ) {
46+ permissionsUrl = queryParams . siteUrl + "/api/datasets/" + queryParams . datasetid + "/userPermissions" ;
47+ if ( queryParams . key ) {
48+ permissionsUrl += ( permissionsUrl . includes ( '?' ) ? '&' : '?' ) + "key=" + queryParams . key ;
49+ }
50+ }
51+ if ( permissionsUrl ) {
52+ try {
53+ const response = await fetch ( permissionsUrl ) ;
54+ if ( response . ok ) {
55+ const json = await response . json ( ) ;
56+ if ( json . status === 'OK' && json . data && json . data . permissions ) {
57+ canRedact = json . data . permissions . includes ( 'EditDataset' ) ;
58+ }
59+ }
60+ } catch ( error ) {
61+ console . error ( "Error checking permissions:" , error ) ;
62+ }
63+ }
64+ }
4065
4166var wait ;
4267var cy ;
@@ -50,7 +75,14 @@ function parseData(data, filejson) {
5075 $ ( '<span/>' ) . text ( $ . i18n ( 'refiqdaParsingProject' ) ) . appendTo ( wait ) ;
5176 wait . appendTo ( $ ( '.preview' ) ) ;
5277
53- new Promise ( ( resolve ) => setTimeout ( resolve , 500 ) ) . then ( ( ) => { parseData2 ( data ) } ) ;
78+ checkPermissions ( ) . then ( ( ) => {
79+ new Promise ( ( resolve ) => setTimeout ( resolve , 500 ) ) . then ( ( ) => {
80+ parseData2 ( data ) ;
81+ if ( canRedact && ! redactedMode ) {
82+ checkForRedactedFile ( ) ;
83+ }
84+ } ) ;
85+ } ) ;
5486}
5587
5688// Reads the project file and walks through the XML creating tables for all the entry types
@@ -69,6 +101,15 @@ function parseData2(data) {
69101 filterBlock . append ( $ ( "<h2/>" ) . html ( $ . i18n ( 'refiqdaEnableFilteringBy' ) ) ) ;
70102 filterBlock . append ( $ ( "<p/>" ) . html ( $ . i18n ( 'refiqdaFilteringInstructions' ) ) ) ;
71103 const filterBy = $ ( '<select/>' ) . prop ( 'id' , 'filterby' ) . appendTo ( filterBlock ) ;
104+ if ( canRedact && ! redactedMode ) {
105+ $ ( '<button/>' )
106+ . addClass ( 'btn btn-danger delete-redacted-btn' )
107+ . text ( $ . i18n ( 'refiqdaDeleteRedacted' ) )
108+ . css ( 'margin-left' , '10px' )
109+ . hide ( )
110+ . click ( deleteRedactedFile )
111+ . appendTo ( filterBlock ) ;
112+ }
72113 filterBy . append ( $ ( '<option/>' ) . prop ( 'value' , 'None' ) . text ( $ . i18n ( 'refiqdaNoFiltering' ) ) ) ;
73114 //As tables are created, they will be added to the option list here
74115
@@ -177,8 +218,10 @@ function parseData2(data) {
177218 } ;
178219 dataTableConfig . buttons = [
179220 'selectAll' ,
180- 'selectNone' ,
181- {
221+ 'selectNone'
222+ ] ;
223+ if ( canRedact ) {
224+ dataTableConfig . buttons . push ( {
182225 text : $ . i18n ( 'refiqdaRedact' ) ,
183226 className : 'redact-btn' ,
184227 titleAttr : $ . i18n ( 'refiqdaRedactCodeTooltip' ) ,
@@ -191,8 +234,8 @@ function parseData2(data) {
191234 redactCodes ( codeGuids ) ;
192235 } ,
193236 enabled : false
194- }
195- ] ;
237+ } ) ;
238+ }
196239 }
197240
198241 if ( hasColorAttribute ) {
@@ -253,7 +296,9 @@ function parseData2(data) {
253296 if ( filterBy . val ( ) === 'Codes' ) {
254297 codeDataTable . on ( 'select deselect' , function ( ) {
255298 var selectedRows = codeDataTable . rows ( { selected : true } ) . count ( ) ;
256- codeDataTable . button ( '.redact-btn' ) . enable ( selectedRows > 0 ) ;
299+ if ( canRedact ) {
300+ codeDataTable . button ( '.redact-btn' ) . enable ( selectedRows > 0 ) ;
301+ }
257302 } ) ;
258303 }
259304
@@ -692,8 +737,10 @@ $("#filterby")
692737 } ;
693738 codeConfig . buttons = [
694739 'selectAll' ,
695- 'selectNone' ,
696- {
740+ 'selectNone'
741+ ] ;
742+ if ( canRedact ) {
743+ codeConfig . buttons . push ( {
697744 text : $ . i18n ( 'refiqdaRedact' ) ,
698745 className : 'redact-btn' ,
699746 titleAttr : $ . i18n ( 'refiqdaRedactCodeTooltip' ) ,
@@ -706,8 +753,8 @@ $("#filterby")
706753 redactCodes ( codeGuids ) ;
707754 } ,
708755 enabled : false
709- }
710- ] ;
756+ } ) ;
757+ }
711758 }
712759
713760 if ( hasColorColumn ) {
@@ -770,7 +817,9 @@ $("#filterby")
770817 if ( $ ( '#filterby' ) . val ( ) === 'Codes' ) {
771818 codeDataTable . on ( 'select deselect' , function ( ) {
772819 var selectedRows = codeDataTable . rows ( { selected : true } ) . count ( ) ;
773- codeDataTable . button ( '.redact-btn' ) . enable ( selectedRows > 0 ) ;
820+ if ( canRedact ) {
821+ codeDataTable . button ( '.redact-btn' ) . enable ( selectedRows > 0 ) ;
822+ }
774823 } ) ;
775824 }
776825
@@ -808,30 +857,34 @@ $("#filterby")
808857 } ;
809858 dtOptions . buttons = [
810859 'selectAll' ,
811- 'selectNone' ,
812- {
813- text : $ . i18n ( 'refiqdaRedact' ) ,
814- className : 'redact-btn' ,
815- titleAttr : $ . i18n ( 'refiqdaRedactSourceTooltip' ) ,
816- action : function ( e , dt , node , config ) {
817- let selectedRows = dt . rows ( { selected : true } ) ;
818- let sourceGuids = [ ] ;
819- selectedRows . nodes ( ) . to$ ( ) . each ( function ( ) {
820- sourceGuids . push ( $ ( this ) . data ( 'guid' ) ) ;
821- } ) ;
822- redactSources ( sourceGuids ) ;
823- } ,
824- enabled : false
825- }
860+ 'selectNone'
826861 ] ;
862+ if ( canRedact ) {
863+ dtOptions . buttons . push ( {
864+ text : $ . i18n ( 'refiqdaRedact' ) ,
865+ className : 'redact-btn' ,
866+ titleAttr : $ . i18n ( 'refiqdaRedactSourceTooltip' ) ,
867+ action : function ( e , dt , node , config ) {
868+ let selectedRows = dt . rows ( { selected : true } ) ;
869+ let sourceGuids = [ ] ;
870+ selectedRows . nodes ( ) . to$ ( ) . each ( function ( ) {
871+ sourceGuids . push ( $ ( this ) . data ( 'guid' ) ) ;
872+ } ) ;
873+ redactSources ( sourceGuids ) ;
874+ } ,
875+ enabled : false
876+ } ) ;
877+ }
827878 }
828879
829880 sourceDataTable = new DataTable ( ".sourcetable" , dtOptions ) ;
830881
831882 if ( filterBy . val ( ) === 'Sources' ) {
832883 sourceDataTable . on ( 'select deselect' , function ( ) {
833884 var selectedRows = sourceDataTable . rows ( { selected : true } ) . count ( ) ;
834- sourceDataTable . button ( '.redact-btn' ) . enable ( selectedRows > 0 ) ;
885+ if ( canRedact ) {
886+ sourceDataTable . button ( '.redact-btn' ) . enable ( selectedRows > 0 ) ;
887+ }
835888 } ) ;
836889 }
837890
@@ -1416,7 +1469,16 @@ async function uploadRedactedFile(blob, filename) {
14161469 formData . append ( "type" , "qda" ) ;
14171470
14181471 console . log ( `Uploading redacted file: ${ filename } ` ) ;
1419- const response = await fetch ( queryParams . signedUrls . uploadRedactedFile , {
1472+ let uploadUrl = queryParams . signedUrls ? queryParams . signedUrls . uploadRedactedFile : null ;
1473+ if ( ! uploadUrl && queryParams . siteUrl && queryParams . fileid ) {
1474+ const type = isZipMode ( ) ? 'qdpx' : 'qdc' ;
1475+ uploadUrl = queryParams . siteUrl + "/api/access/datafile/" + queryParams . fileid + "/auxiliary/" + type + "/1.0" ;
1476+ if ( queryParams . key ) {
1477+ uploadUrl += ( uploadUrl . includes ( '?' ) ? '&' : '?' ) + "key=" + queryParams . key ;
1478+ }
1479+ }
1480+
1481+ const response = await fetch ( uploadUrl , {
14201482 method : 'POST' ,
14211483 body : formData ,
14221484 } ) ;
@@ -1429,6 +1491,7 @@ async function uploadRedactedFile(blob, filename) {
14291491 const responseData = await response . json ( ) ;
14301492 console . log ( "Upload successful:" , responseData ) ;
14311493 alert ( $ . i18n ( 'refiqdaRedactSuccess' ) ) ;
1494+ checkForRedactedFile ( ) ;
14321495 } catch ( error ) {
14331496 console . error ( "Error during upload:" , error ) ;
14341497 alert ( $ . i18n ( 'refiqdaRedactError' , error . message ) ) ;
@@ -1497,3 +1560,59 @@ function redactCodes(guidsToRedact) {
14971560 uploadRedactedFile ( redactedXmlBlob , redactedFilename ) ;
14981561 }
14991562}
1563+
1564+ async function checkForRedactedFile ( ) {
1565+ let listUrl = queryParams . signedUrls ? queryParams . signedUrls . listAuxiliaryFiles : null ;
1566+ if ( ! listUrl && queryParams . siteUrl && queryParams . fileid ) {
1567+ listUrl = queryParams . siteUrl + "/api/access/datafile/" + queryParams . fileid + "/auxiliary" ;
1568+ if ( queryParams . key ) {
1569+ listUrl += ( listUrl . includes ( '?' ) ? '&' : '?' ) + "key=" + queryParams . key ;
1570+ }
1571+ }
1572+ if ( listUrl ) {
1573+ try {
1574+ const response = await fetch ( listUrl ) ;
1575+ if ( response . ok ) {
1576+ const auxFiles = await response . json ( ) ;
1577+ const type = isZipMode ( ) ? 'qdpx' : 'qdc' ;
1578+ redactedFileExists = auxFiles . some ( f => f . formatTag === type && f . formatVersion === '1.0' ) ;
1579+ if ( redactedFileExists ) {
1580+ $ ( '.delete-redacted-btn' ) . show ( ) ;
1581+ } else {
1582+ $ ( '.delete-redacted-btn' ) . hide ( ) ;
1583+ }
1584+ }
1585+ } catch ( error ) {
1586+ console . error ( "Error checking for redacted file:" , error ) ;
1587+ }
1588+ }
1589+ }
1590+
1591+ async function deleteRedactedFile ( ) {
1592+ if ( confirm ( $ . i18n ( 'refiqdaDeleteConfirm' ) ) ) {
1593+ try {
1594+ let deleteUrl = queryParams . signedUrls ? queryParams . signedUrls . deleteRedactedFile : null ;
1595+ if ( ! deleteUrl && queryParams . siteUrl && queryParams . fileid ) {
1596+ const type = isZipMode ( ) ? 'qdpx' : 'qdc' ;
1597+ deleteUrl = queryParams . siteUrl + "/api/access/datafile/" + queryParams . fileid + "/auxiliary/" + type + "/1.0" ;
1598+ if ( queryParams . key ) {
1599+ deleteUrl += ( deleteUrl . includes ( '?' ) ? '&' : '?' ) + "key=" + queryParams . key ;
1600+ }
1601+ }
1602+ const response = await fetch ( deleteUrl , {
1603+ method : 'DELETE'
1604+ } ) ;
1605+ if ( response . ok ) {
1606+ alert ( $ . i18n ( 'refiqdaDeleteSuccess' ) ) ;
1607+ redactedFileExists = false ;
1608+ $ ( '.delete-redacted-btn' ) . hide ( ) ;
1609+ } else {
1610+ const errorText = await response . text ( ) ;
1611+ throw new Error ( `Delete failed: ${ response . statusText } - ${ errorText } ` ) ;
1612+ }
1613+ } catch ( error ) {
1614+ console . error ( "Error deleting redacted file:" , error ) ;
1615+ alert ( $ . i18n ( 'refiqdaDeleteError' , error . message ) ) ;
1616+ }
1617+ }
1618+ }
0 commit comments