@@ -130,4 +130,43 @@ export class CollectionLandingComponent implements OnInit, OnDestroy {
130130 }
131131 } ) ;
132132 }
133+
134+ exportSessionsToCSV ( ) : void {
135+ const col = this . collection ( ) ;
136+ if ( ! col || col . accessible_curtains . length === 0 ) {
137+ return ;
138+ }
139+
140+ const baseUrl = location . origin + '/#/' ;
141+ const headers = [ 'Name' , 'Description' , 'Link' , 'Curtain Type' , 'Created' , 'Contact' ] ;
142+ const rows = col . accessible_curtains . map ( curtain => {
143+ const link = baseUrl + curtain . link_id ;
144+ return [
145+ this . escapeCSV ( curtain . description || 'Untitled Session' ) ,
146+ this . escapeCSV ( col . description || '' ) ,
147+ this . escapeCSV ( link ) ,
148+ this . escapeCSV ( curtain . curtain_type ) ,
149+ this . escapeCSV ( this . formatDate ( curtain . created ) ) ,
150+ this . escapeCSV ( col . owner_username )
151+ ] . join ( ',' ) ;
152+ } ) ;
153+
154+ const csvContent = [ headers . join ( ',' ) , ...rows ] . join ( '\n' ) ;
155+ const blob = new Blob ( [ csvContent ] , { type : 'text/csv;charset=utf-8;' } ) ;
156+ const url = URL . createObjectURL ( blob ) ;
157+ const link = document . createElement ( 'a' ) ;
158+ link . setAttribute ( 'href' , url ) ;
159+ link . setAttribute ( 'download' , `${ col . name . replace ( / [ ^ a - z A - Z 0 - 9 ] / g, '_' ) } _sessions.csv` ) ;
160+ document . body . appendChild ( link ) ;
161+ link . click ( ) ;
162+ document . body . removeChild ( link ) ;
163+ URL . revokeObjectURL ( url ) ;
164+ }
165+
166+ private escapeCSV ( value : string ) : string {
167+ if ( value . includes ( ',' ) || value . includes ( '"' ) || value . includes ( '\n' ) ) {
168+ return `"${ value . replace ( / " / g, '""' ) } "` ;
169+ }
170+ return value ;
171+ }
133172}
0 commit comments