1+
2+ /*MD
3+
4+ ## DLF Archive
5+
6+ Example from <http://localhost:9005/Dropbox/Music/dlf/Querkoepfe/index.md>:
7+
8+ ```javascript
9+ import DLFArchive from "demos/dlf-archive.js"
10+
11+ var container = lively.query(this, "lively-container")
12+ new DLFArchive("Querköpfe", "Wed_2105_querkoepfe", container.getDir()).createView()
13+ ```
14+
15+
16+ MD*/
17+
18+
19+ import Strings from 'src/client/strings.js'
20+
21+ export default class DLFArchive {
22+
23+ constructor ( sendung , pattern , dirURL ) {
24+ this . dirURL = dirURL
25+ this . sendung = sendung
26+ this . pattern = pattern
27+ }
28+
29+
30+ async loadDLFSendung ( isoDate ) {
31+ var tab = await fetch ( `cached:http://localhost:9005/Dropbox/share/DLF/extract/${ isoDate } .tab` ) . then ( r => r . text ( ) )
32+
33+ var programm = tab . split ( / \n / g) . map ( ea => ea . split ( / \t / ) )
34+
35+
36+ // deals with corona iregularities
37+ var programmCollection = programm . find ( ea => ea [ 1 ] && ea [ 1 ] . startsWith ( "Der Kultur-Abend" ) )
38+ if ( programmCollection ) {
39+ let div = < div > </ div >
40+ div . innerHTML = programmCollection [ 2 ]
41+ var subs = [ ]
42+ var last = [ "nothing" , "nothing" , "" ]
43+ for ( var child of div . childNodes ) {
44+ if ( child . classList . contains ( "subDescription" ) ) {
45+ var spans = child . querySelectorAll ( "span" )
46+ last = [ spans [ 0 ] . textContent , spans [ 1 ] . textContent , "" ]
47+ subs . push ( last )
48+ } else {
49+ last [ 2 ] += child . outerHTML + "\n"
50+ }
51+ }
52+ programm . push ( ...subs )
53+ }
54+
55+ var sendung = programm . filter ( ea => ea [ 1 ] && ea [ 1 ] . startsWith ( this . sendung ) ) [ 0 ]
56+ if ( ! sendung || ! sendung [ 2 ] ) return
57+ let div = < div > </ div >
58+ div . innerHTML = sendung [ 2 ]
59+ var p = div . querySelector ( "p" )
60+ if ( p ) {
61+ return p . innerHTML . split ( / < b r > / )
62+ }
63+ }
64+
65+
66+ async loadProgramInfo ( item ) {
67+ var m = item . file . name . match ( / ( 2 0 \d \d - \d \d - \d \d ) / )
68+ if ( m && m [ 1 ] ) {
69+ var isoDate = m [ 1 ]
70+ } else {
71+ return
72+ }
73+ var info = await this . loadDLFSendung ( isoDate )
74+ return info
75+ }
76+
77+
78+ async selectItem ( item ) {
79+ if ( this . lastSelected ) this . lastSelected . classList . remove ( "selected" )
80+ item . classList . add ( "selected" )
81+ this . lastSelected = item
82+
83+ var info = await this . loadProgramInfo ( item )
84+ if ( ! info ) {
85+ this . details . innerHTML = "no details"
86+ } else {
87+ this . details . innerHTML = JSON . stringify ( info )
88+ this . lastSelected . info = info
89+ }
90+
91+ }
92+
93+ onItemClick ( evt , item ) {
94+
95+ this . selectItem ( item )
96+
97+ // if (item.classList.contains("selected")) {
98+ // item.classList.remove("selected")
99+ // } else {
100+ // item.classList.add("selected")
101+ // }
102+ }
103+
104+ async newFilenameForItem ( item ) {
105+
106+ if ( ! item . file ) return
107+
108+ var rawPattern = this . pattern
109+
110+ var filename = item . file . name
111+ if ( ! filename . match ( rawPattern ) ) {
112+ // lively.notify("file has already a custom name")
113+ return
114+ }
115+
116+ if ( ! item . info ) {
117+ item . info = await this . loadProgramInfo ( item )
118+ if ( ! item . info ) {
119+ console . log ( "could not load DLF program info for " + item . file )
120+ return
121+ }
122+ }
123+
124+
125+ var info = item . info
126+ var s = this . sendung
127+ if ( this . sendung == "Hörspiel" ) { // #TODO pull this out
128+ s += " - " + info [ 0 ]
129+ }
130+ s += " - " + info [ 1 ]
131+ if ( info [ 2 ] ) s += " - " + info [ 2 ]
132+ s = s . replace ( / / g, "_" )
133+ s = s . replace ( / [: .\/ ] / g, "_" )
134+ s = s . replace ( / [ „ " ] / g, "" )
135+ s = s . replace ( / _ + / g, "_" )
136+
137+ var newFilename = filename . replace ( rawPattern , s )
138+ return newFilename
139+ }
140+
141+
142+
143+ async onRenameButton ( evt ) {
144+ if ( ! this . lastSelected ) return
145+
146+ var newFilename = await this . newFilenameForItem ( this . lastSelected )
147+
148+ if ( ! newFilename ) {
149+ lively . warn ( "could not generate new filename" )
150+ return
151+ }
152+ this . lastSelected . newFilename = newFilename
153+ this . renameItem ( this . lastSelected )
154+ // lively.warn("not implemented yet")
155+
156+ }
157+
158+ async renameItem ( item , dontAsk ) {
159+ if ( ! item . newFilename ) return ;
160+
161+ var filename = item . file . name
162+
163+ var fromURL = this . dirURL + encodeURI ( filename )
164+ var toURL = this . dirURL + encodeURI ( item . newFilename )
165+
166+
167+ if ( ! dontAsk && ! await lively . confirm ( "rename " + filename + " -> " + item . newFilename + " in " + this . dirURL ) ) {
168+ return "cancel"
169+ }
170+ var resp = await lively . files . moveFile ( fromURL , toURL )
171+ if ( resp . status == 200 ) {
172+ item . innerHTML = item . newFilename
173+ delete item . newFilename
174+ } else {
175+ item . style . backgroundColor = "red"
176+ }
177+ }
178+
179+ async onPreviewButton ( ) {
180+ for ( var item of this . items ) {
181+ var newFilename = await this . newFilenameForItem ( item )
182+ if ( newFilename ) {
183+ item . newFilename = newFilename
184+ item . innerHTML = "rename " + item . file . name + " -> <b>" + newFilename + "</b>"
185+ } else {
186+ item . style . color = "gray"
187+ }
188+ }
189+ }
190+
191+ async onRenameAllButton ( ) {
192+ for ( var item of this . items ) {
193+ await this . renameItem ( item , true )
194+ }
195+ }
196+
197+ async createView ( ) {
198+ var stats = await fetch ( this . dirURL , { method : "OPTIONS" } ) . then ( r => r . json ( ) )
199+
200+
201+ this . items = stats . contents
202+ . sortBy ( ea => ea . name )
203+ . map ( ea => {
204+ var item = < li > { ea . name } </ li >
205+ item . file = ea
206+ item . addEventListener ( "click" , evt => this . onItemClick ( evt , item ) )
207+ return item
208+ } )
209+
210+ var list = < ul id = "list" > { ...this . items } </ ul >
211+ var style = document . createElement ( "style" ) // #ISSUE style tags conflict with Markdown rewriting....
212+ style . innerHTML = `
213+ li.selected {
214+ background-color: lightgray
215+ }
216+
217+ #pane {
218+ position: absolute;
219+ width: 100%;
220+ top: 200px;
221+ height: calc(100% - 200px);
222+ overflow: auto;
223+
224+ }
225+ #buttons: {
226+
227+ }
228+
229+
230+ #list {
231+ }
232+
233+ h1, #buttons, #details {
234+ margin: 20px;
235+ }
236+
237+ `
238+ this . details = < div id = "details" > </ div >
239+ // #TODO relative positioning does not work with 100% calculations...
240+ return < div style = "position:absolute;top:0px; left:0px;width:100%; height:100%" >
241+ { style }
242+ < h1 > { this . sendung } </ h1 >
243+ < div id = "buttons" >
244+ < button click = { evt => this . onRenameButton ( evt ) } > rename selected</ button >
245+ < button click = { evt => this . onPreviewButton ( evt ) } > preview all</ button >
246+ < button click = { evt => this . onRenameAllButton ( evt ) } > rename all</ button >
247+
248+ </ div >
249+ { this . details }
250+ < div id = "pane" >
251+ { list }
252+ </ div >
253+ </ div >
254+ }
255+
256+ }
0 commit comments