From 565d576f704c337b82a583d192c77d43bfca2648 Mon Sep 17 00:00:00 2001 From: "B. Stack" Date: Wed, 10 Aug 2022 22:35:07 -0400 Subject: WIP: add upload functionality, part 1 The upload button now calls logic, which does a rudimentary upload. The new item can successfully be saved to the server, but the event does not immediately show up in the InfCloud view. The user has to reload the web page to see the new event, which of course is not ideal. There must be a way to add the new object immediately. --- radicale_infcloud/web/cache_handler.js | 63 +-- radicale_infcloud/web/data_process.js | 801 ++++++++++++++++++++++++++++++++- radicale_infcloud/web/forms.js | 37 ++ radicale_infcloud/web/index.html | 1 + radicale_infcloud/web/interface.js | 39 ++ 5 files changed, 903 insertions(+), 38 deletions(-) (limited to 'radicale_infcloud/web') diff --git a/radicale_infcloud/web/cache_handler.js b/radicale_infcloud/web/cache_handler.js index e21fb63..4926b20 100644 --- a/radicale_infcloud/web/cache_handler.js +++ b/radicale_infcloud/web/cache_handler.js @@ -43,37 +43,40 @@ window.applicationCache.addEventListener('updateready', function(){ // Check if a new cache is available on page load. window.addEventListener('load', function(e) { - window.applicationCache.addEventListener('cached', function(e) - { - if(!isUserLogged) - window.location.reload(); - else - $('#cacheDialog').css('display','block'); - }, false); + if(window.applicationCache) + { + window.applicationCache.addEventListener('cached', function(e) + { + if(!isUserLogged) + window.location.reload(); + else + $('#cacheDialog').css('display','block'); + }, false); - window.applicationCache.addEventListener('updateready', function(e) - { - if(!isUserLogged) - window.location.reload(); - else - $('#cacheDialog').css('display','block'); - }, false); + window.applicationCache.addEventListener('updateready', function(e) + { + if(!isUserLogged) + window.location.reload(); + else + $('#cacheDialog').css('display','block'); + }, false); - window.applicationCache.addEventListener('obsolete', function(e) - { - if(!isUserLogged) - window.location.reload(); - else - $('#cacheDialog').css('display','block'); - }, false); + window.applicationCache.addEventListener('obsolete', function(e) + { + if(!isUserLogged) + window.location.reload(); + else + $('#cacheDialog').css('display','block'); + }, false); - window.applicationCache.addEventListener('noupdate', function(e) - { - if(!isUserLogged) - { - clearInterval(globalCacheUpdateInterval); - globalCacheUpdateInterval=setInterval(function(){window.applicationCache.update();}, 300000); - //$('#LoginPage .window').css('display', 'inline-block'); - } - }, false); + window.applicationCache.addEventListener('noupdate', function(e) + { + if(!isUserLogged) + { + clearInterval(globalCacheUpdateInterval); + globalCacheUpdateInterval=setInterval(function(){window.applicationCache.update();}, 300000); + //$('#LoginPage .window').css('display', 'inline-block'); + } + }, false); + }; }, false); diff --git a/radicale_infcloud/web/data_process.js b/radicale_infcloud/web/data_process.js index bdbf711..e71f23e 100644 --- a/radicale_infcloud/web/data_process.js +++ b/radicale_infcloud/web/data_process.js @@ -1067,6 +1067,7 @@ function checkAndFixMultipleUID(vcalendar, isEvent) } return eventStringArray; } + function dataToVcalendar(operation, accountUID, inputUID, inputEtag, delUID,isFormHidden, deleteMode) { var vevent=false, @@ -1341,11 +1342,6 @@ function dataToVcalendar(operation, accountUID, inputUID, inputEtag, delUID,isFo { if(globalSettings.timezonesupport.value) sel_option=$('#timezone').val(); - //else - //{ - // if(inputEvents.length>0) - // sel_option=inputEvents[0].timeZone; - //} if(sel_option=='UTC') { @@ -2148,9 +2144,6 @@ function dataToVcalendar(operation, accountUID, inputUID, inputEtag, delUID,isFo if($('#status').val()!='NONE') { - - //if((value=$('[id="vcalendar_editor"] [data-type="\\%note"]').find('textarea').val())!='') - //{ if(vCalendar.tplM['contentline_STATUS']!=null && (process_elem=vCalendar.tplM['contentline_STATUS'][0])!=undefined) { // replace the object and related objects' group names (+ append the related objects after the processed) @@ -3447,6 +3440,7 @@ function getDateFromDay(objComponent, t, disableRecursion,uid) return {offsetFrom:objComponent.tzOffsetFROM, offsetTo: objComponent.tzOffsetTO, startDate: dayLightStartDate}; } +/* FINDTHIS */ function vcalendarToData(inputCollection, inputEvent, isNew) { var vcalendarOrig=inputEvent.vcalendar; @@ -7793,3 +7787,794 @@ function normalizeVcard(vcardString) return vcard_out_grouped.join(''); } + +/* START stackrpms functions 2022-08-10 + * duplicated and modified from function vcalendarToData() on line 3443 + */ +function stringToVevent(inputCollection, vstring, uid, etag, isNew) +{ + //vcalendarToData(inputCollection, inputEvent, isNew) + //var vcalendarOrig=inputEvent.vcalendar; + var vcalendarOrig=vstring; + var eventArray=new Array(); + + //CHECK CALSCALE + var elem=vcalendarOrig.match(vCalendar.pre['contentline_CALSCALE']); + if(elem!=null) + { + calscale=elem[0].match(vCalendar.pre['contentline_parse'])[4]; + if(calscale!='GREGORIAN') + { + console.log("Error:'"+uid+"': Unsupported calscale in:"+vcalendarOrig); + return false; + } + } + //CHECK VERSION + var elemV=vcalendarOrig.match(vCalendar.pre['contentline_VERSION']); + if(elemV!=null) + { + var ver=elemV[0].match(vCalendar.pre['contentline_parse'])[4]; + if(ver!='2.0') + { + console.log("Error:'"+uid+"': Unsupported version ("+ver+") in:"+vcalendarOrig); + return false; + } + } + + //FIX TIMEZONE + var beginTimeZone=vcalendarOrig.indexOf('BEGIN:VTIMEZONE'); + var startEndTimeZone=vcalendarOrig.lastIndexOf('END:VTIMEZONE'); + var endTimeZone=0; + + var rid=uid.substring(0, uid.lastIndexOf('/')+1); + var evid=uid.substring(uid.lastIndexOf('/')+1, uid.length); + + var isChange=false, + needReload=false; + + if(!isNew) + { + var events=findEventInArray(uid, true); + if(events!='') + { + if(events.etag!=etag) + { + for(var i=0; i'+name+" "+localization[globalInterfaceLanguage].repeatChangeTxt); + $('#repeatConfirmBoxQuestion').html(localization[globalInterfaceLanguage].repeatChangeTxtClose); + } + else + needReload=true; + } + } + isChange=true; + } + } + } + + if((beginTimeZone!=-1) && (startEndTimeZone!=-1)) + { + for(i=(startEndTimeZone+2);i0) + isRepeat=true; + for(var i=0;i1 || tzName=='UTC') + { + if(tzName!='UTC') + tzName=$.trim(dtStartTimezone[1]); + var finTZ = checkTimezone(tzName); + if(finTZ!=null) + tzName = finTZ; + if(globalSettings.timezonesupport.value && tzName in timezones) + { + valOffsetFrom=getOffsetByTZ(tzName, t); + intOffset=(getLocalOffset(t)*-1*1000)-valOffsetFrom.getSecondsFromOffset()*1000; + } + } + else if(processedTimezones.indexOf(tzName)==-1) + { + if(timeZonesEnabled.indexOf(tzName)==-1) + timeZonesEnabled.push('local'); + processedTimezones.push('local'); + } + if(tzName!='' && tzName != 'local') + if(processedTimezones.indexOf(tzName)==-1) + { + if(timeZonesEnabled.indexOf(tzName)==-1) + timeZonesEnabled.push(tzName); + processedTimezones.push(tzName); + } + } + else + tzName = globalSessionTimeZone; + realStart=$.fullCalendar.parseDate(help1); + //inputEvent.start=$.fullCalendar.parseDate(help1); + start=$.fullCalendar.parseDate(help1); + if(intOffset) + { + //inputEvent.start.setTime(inputEvent.start.getTime()+intOffset); + start.setTime(start.getTime()+intOffset); + } + if(exDate_array!=null) + for(var j=0;j1 || tzNameA=='UTC') + { + if(tzNameA!='UTC' && dtStartTimezoneA[0]==';TZID') + tzNameA=$.trim(dtStartTimezoneA[1]); + var finTZ = checkTimezone(tzNameA); + if(finTZ!=null) + tzNameA = finTZ; + if(globalSettings.timezonesupport.value && tzNameA in timezones) + { + var valOffsetFromA=getOffsetByTZ(tzNameA, alarmTimeA); + intOffsetA=getOffsetByTZ(tzName, alarmTimeA).getSecondsFromOffset()*1000-valOffsetFromA.getSecondsFromOffset()*1000; + } + } + else if(processedTimezones.indexOf(tzName)==-1) + { + if(timeZonesEnabled.indexOf(tzName)==-1) + timeZonesEnabled.push('local'); + processedTimezones.push('local'); + } + if(tzNameA!='' && tzNameA != 'local') + if(processedTimezones.indexOf(tzNameA)==-1) + { + if(timeZonesEnabled.indexOf(tzNameA)==-1) + timeZonesEnabled.push(tzNameA); + processedTimezones.push(tzNameA); + } + if(intOffsetA!='') + alarmTimeA.setTime(alarmTimeA.getTime()+intOffsetA); + alertTime[j]=$.fullCalendar.formatDate(alarmTimeA,"yyyy-MM-dd'T'HH:mm:ss"); + } + else + { + alertTime[j]=0; + if(value.indexOf('W')!=-1) + alertTime[j]=parseAlarmWeek(value); + else if(value.indexOf('D')!=-1) + alertTime[j]=parseAlarmDay(value); + else if(value.indexOf('T')!=-1) + alertTime[j]=parseAlarmTime(value); + if(parsed[4].charAt(0)=="-") + alertTime[j]="-"+alertTime[j]; + else + alertTime[j]="+"+alertTime[j]; + } + } + } + else + break; + + noteA=alarmArray[j].match(vCalendar.pre['contentline_NOTE']); + if(noteA!=null) + { + parsed=noteA[0].match(vCalendar.pre['contentline_parse']); + alertNote[j]=parsed[4]; + } + else + alertNote[j]='Default note'; + } + } + } + + vcalendar_element=vcalendar.match(vCalendar.pre['contentline_LOCATION']); + if(vcalendar_element!=null) + { + parsed=vcalendar_element[0].match(vCalendar.pre['contentline_parse']); + location=vcalendarUnescapeValue(parsed[4]); + } + + vcalendar_element=vcalendar.match(vCalendar.pre['contentline_NOTE']); + if(vcalendar_element!=null) + { + parsed=vcalendar_element[0].match(vCalendar.pre['contentline_parse']); + note=vcalendarUnescapeValue(parsed[4]); + } + + vcalendar_element=vcalendar.match(vCalendar.pre['contentline_SUMMARY']); + if(vcalendar_element!=null) + { + parsed=vcalendar_element[0].match(vCalendar.pre['contentline_parse']); + title=vcalendarUnescapeValue(parsed[4]); + } + + vcalendar_element=vcalendar.match(vCalendar.pre['contentline_PRIORITY']); + if(vcalendar_element!=null) + { + parsed=vcalendar_element[0].match(vCalendar.pre['contentline_parse']); + priority=vcalendarUnescapeValue(parsed[4]); + } + + var index=0; + for(var p=0;p1 || tzName=='UTC') + { + if(tzName!='UTC') + tzName=$.trim(dtStartTimezone[1]); + var finTZ = checkTimezone(tzName); + if(finTZ!=null) + tzName = finTZ; + if(globalSettings.timezonesupport.value && tzName in timezones) + { + valOffsetFrom=getOffsetByTZ(tzName, t1); + intOffset=(getLocalOffset(t1)*-1*1000)-valOffsetFrom.getSecondsFromOffset()*1000; + } + } + else if(processedTimezones.indexOf(tzName)==-1) + { + if(timeZonesEnabled.indexOf(tzName)==-1) + timeZonesEnabled.push('local'); + processedTimezones.push('local'); + } + //realEnd=$.fullCalendar.parseDate(help); + //help1+=valOffsetFrom; + + if(tzName!='' && tzName != 'local') + if(processedTimezones.indexOf(tzName)==-1) + { + if(timeZonesEnabled.indexOf(tzName)==-1) + timeZonesEnabled.push(tzName); + processedTimezones.push(tzName); + } + } + else + tzName = globalSessionTimeZone; + + realEnd=$.fullCalendar.parseDate(help); + //inputEvent.end=$.fullCalendar.parseDate(help); + end=$.fullCalendar.parseDate(help); + if(intOffset) + { + //inputEvent.end.setTime(inputEvent.end.getTime()+intOffset); + end.setTime(end.getTime()+intOffset); + } + } + else + return false; + + if(globalVisibleCalDAVCollections.indexOf(rid)!=-1 || isChange || isNew) + { + if(isRepeat) + { + var futureRLimit = new Date(globalToLoadedLimit.getTime()) + futureRLimit.setDate(futureRLimit.getDate()+14); + var ruleString=vcalendar.match(vCalendar.pre['contentline_RRULE2'])[0].match(vCalendar.pre['contentline_parse'])[4]; + //inputEvent.isRepeat=true; + if(realStart) + var varDate=new Date(realStart.getTime()); + else + var varDate=new Date(start.getTime()); + + if(realEnd) + var varEndDate=new Date(realEnd.getTime()); + else + var varEndDate=new Date(end.getTime()); + + var lastGenDate=''; + var repeatStart=new Date(varDate.getTime()); + var repeatEnd=new Date(varEndDate.getTime()); + var untilDate='',realUntilDate='',realUntil=''; + + if(until!=='') + { + if(isUntilDate) + { + if(until.indexOf('T')!=-1) + { + var uString = until.substring(0, 4)+'-'+until.substring(4, 6)+'-'+until.substring(6, 8)+'T'+until.substring(9, 11)+':'+until.substring(11, 13)+':'+until.substring(13, 15); + var ut=$.fullCalendar.parseDate(uString); + if(ut==null) + return false; + if(ut.toString()=='Invalid Date') + return false; + if(!all) + { + if(globalSettings.timezonesupport.value && tzName in timezones) + valOffsetFrom=getOffsetByTZ(tzName, ut); + if(valOffsetFrom) + { + var intOffset=valOffsetFrom.getSecondsFromOffset()*1000; + ut.setTime(ut.getTime()+intOffset); + } + } + untilDate = new Date(ut.getTime()); + } + else + { + untilDate=$.fullCalendar.parseDate(until.substring(0, 4)+'-'+until.substring(4, 6)+'-'+until.substring(6, 8)); + untilDate.setHours(realStart.getHours()); + untilDate.setMinutes(realStart.getMinutes()); + untilDate.setSeconds(realStart.getSeconds()); + } + + realUntil=''; + } + else + { + untilDate=''; + realUntil=until; + + } + realUntilDate=untilDate; + //inputEvent.untilDate=untilDate; + } + else + { + untilDate=new Date(futureRLimit.getTime()); + realUntilDate=''; + //inputEvent.untilDate='never'; + } + var repeatCount=0, realRepeatCount=0; + + if(true) + { + if(alertTime.length>0) + { + var aTime=''; + var now=new Date(); + if(!inputCollection.ignoreAlarms) + alertTimeOut=setAlertTimeouts(false,alertTime, start, end, {allDay:all, title:title}, true, uid); + } + realRepeatCount++; + var checkRec=isInRecurrenceArray(varDate,stringUID,recurrence_id_array, tzName); + + if(exDates.length>0) + if(exDates.indexOf(varDate.toString())!=-1) + checkRec=true; + if(!checkRec) + { + repeatCount++; + var tmpObj=new items(etag, start, end, title, all, uid, rid, evid, note, inputCollection.displayValue, alertTime, alertNote, realUntilDate, frequency, interval, realUntil, repeatStart, repeatEnd, byMonthDay,repeatCount, realRepeatCount, vcalendar, location, alertTimeOut,tzName, realStart, realEnd, byDay, rec_id,wkst,classType, avail,hrefUrl, compareString,priority,status,ruleString); + globalEventList.displayEventsArray[rid].splice(globalEventList.displayEventsArray[rid].length, 0, tmpObj); + } + } + + var lastGenDate=generateRepeatInstances({ + untilDate:realUntilDate, + repeatStart:varDate, + futureRLimit:futureRLimit, + stringUID:stringUID, + recurrence_id_array:recurrence_id_array, + exDates:exDates, + alertTime:alertTime, + ignoreAlarms:inputCollection.ignoreAlarms, + items:new items(etag, varDate, varEndDate, title, all, uid, rid, evid, note, inputCollection.displayValue, alertTime, alertNote, realUntilDate, frequency, interval, realUntil, repeatStart, repeatEnd, byMonthDay, repeatCount, realRepeatCount, vcalendar, location, alertTimeOut, tzName, realStart, realEnd, byDay, rec_id,wkst,classType, avail,hrefUrl,compareString,priority,status,ruleString) + }); + } + else + { + if(!inputCollection.ignoreAlarms) + alertTimeOut=setAlertTimeouts(false,alertTime, start, end, {allDay:all, title:title},true,uid); + + var tmpObj=new items(etag, start, end, title, all, uid, rid, evid, note, inputCollection.displayValue, alertTime, alertNote, '', '', '', '', '', '', '', '', '', vcalendar, location, alertTimeOut, tzName, realStart, realEnd, byDay, rec_id,wkst,classType, avail,hrefUrl,compareString,priority,status,ruleString); + if(isChange) + { + if(needReload) + showEventForm(null, null, tmpObj, globalJsEvent, 'show', ''); + } + globalEventList.displayEventsArray[rid].splice(globalEventList.displayEventsArray[rid].length, 0, tmpObj); + } + } + } + //inputEvent.isDrawn=true; + return tmpObj; +} +/* END stackrpms functions */ diff --git a/radicale_infcloud/web/forms.js b/radicale_infcloud/web/forms.js index c125820..4e5a1a9 100644 --- a/radicale_infcloud/web/forms.js +++ b/radicale_infcloud/web/forms.js @@ -31,6 +31,39 @@ function updateTodoFormDimensions(setHeight) } } +function dragOverHandler(event) { + //if (window.console) { + // console.log("dragOverHandler",event); + //} + event.preventDefault(); + event.stopPropagation(); +} + +/* Incomplete import process. The function logs to console but does not use the vcard contents. */ +function dropHandler(event) { + if (event) { + event.preventDefault(); + event.stopPropagation(); + if (window.console) { + console.log("dropHandler",event); + } + if(event.dataTransfer && event.dataTransfer && event.dataTransfer.files.length > 0) { + if(window.console){console.log("files",event.dataTransfer.files);} + for (let f of event.dataTransfer.files) { + if(window.console){console.log("file:",f)}; + let reader = new FileReader(); + reader.readAsText(f); + reader.onload = function(){ + if(window.console){console.log(reader.result)}; + //dataToVcalendar('EDIT' + uploadFile(reader.result) + }; + reader.onerror = function(){if(window.console){console.log(reader.error)}}; + } + } + } +} + function updateEventFormDimensions(setHeight) { $('#CAEvent').css('width',''); @@ -2316,6 +2349,7 @@ function showEventForm(date, allDay, calEvent, jsEvent, mod, repeatOne, confirmR if(mod=='show') { $('#saveButton').hide(); + $('#uploadButton').hide(); $('#resetButton').hide(); $('#deleteButton').hide(); if($('#ResourceCalDAVList').find('[data-id="'+calEvent.res_id+'"]').hasClass("resourceCalDAV_item_ro")) @@ -2844,6 +2878,9 @@ function startEditModeEvent() $('#saveButton').show(); $('#resetButton').show(); $('#deleteButton').show(); + /* WORKHERE: hide the uploadButton when editing an existing object */ + $('#uploadButton').show(); + $('#uploadButton').on("drop",dropHandler(event)); $('#downloadButton').hide(); $('#show').val(''); $('#eventDetailsTable :input[disabled]').prop('disabled', false); diff --git a/radicale_infcloud/web/index.html b/radicale_infcloud/web/index.html index 39b8583..a8b95e4 100644 --- a/radicale_infcloud/web/index.html +++ b/radicale_infcloud/web/index.html @@ -629,6 +629,7 @@ along with this program. If not, see . + diff --git a/radicale_infcloud/web/interface.js b/radicale_infcloud/web/interface.js index e5afb8d..745d58d 100644 --- a/radicale_infcloud/web/interface.js +++ b/radicale_infcloud/web/interface.js @@ -1289,6 +1289,45 @@ function addAndEdit(isFormHidden, deleteMode) dataToVcalendar('EDIT',origUID, inputUID, $('#etag').val(), '', isFormHidden, deleteMode); } +/* START stackrpms 2022-08-10 + * uploadFile is a clone of addAndEdit + */ +function uploadFile(fileContents) +{ + var inputUID=''; + if($('#uid').val()!='') + var coll = globalResourceCalDAVList.getEventCollectionByUID($('#uid').val().substring(0, $('#uid').val().lastIndexOf('/')+1)); + else + var coll = globalResourceCalDAVList.getEventCollectionByUID($('#event_calendar').val()); + var res = getAccount(coll.accountUID); + var tmp=res.href.match(vCalendar.pre['hrefRex']); + var origUID=tmp[1]+res.userAuth.userName+'@'+tmp[2]; + if($('#etag').val()!='') + inputUID=$('#uid').val(); + else if($('#event_calendar').val()!='choose') + inputUID = $('#event_calendar').val()+''; + else + return false; + // ripped from data_process.js:1474 + var newUID=globalEventList.getNewUID(); + //process_elem=process_elem.replace('##:::##uid##:::##', newUID); + fileContents = fileContents.replace(/^UID:.*$/gm,String("UID:"+newUID)); + // WORKHERE: Could also try adding inputUID+newUID. Not sure if it helps or hurts. + newEvent = stringToVevent(coll, fileContents, inputUID, $('#etag').val(), true); + console.log(newEvent); + console.log("All day:"); + console.log(newEvent.allDay); + console.log(newEvent.allDay); + // This was an attempt to populate the form. I found it easier to just send the object to the caldav server right away. + // ref: interface.js:2601 + //showEventForm(null, newEvent.allDay, newEvent, null, 'show', ''); + // Just call the caldav operation directly. + //putVcalendarToCollection(accountUID, inputUID, inputEtag, inputS, delUID, 'vevent', isFormHidden, deleteMode, fixedArr); + // putVcalendarToCollection("http://domainjoin@d2-03a/radicale/domainjoin", "http://domainjoin@d2-03a/radicale/domainjoin/4f58b6a8-014f-03b9-ae12-071eb28798de/", "", fileContents, "", 'vevent', undefined, undefined, + return putVcalendarToCollection(coll.accountUID, inputUID, "", fileContents, "", 'vevent', false, false, ""); + // WORKHERE: somehow add this to the globalEventList thing, like adding a brand-new event by hand? +} + function interResourceEdit(op, delUID,isFormHidden) { var inputUID=''; -- cgit