Changed modal from callbacks to promises, Updated readme, Re added save functions to filemanager, active, and autosave components, Started readding upload to filemanager,

This commit is contained in:
xevidos 2020-01-22 10:14:01 -05:00
parent 44cf240e13
commit cefb309df1
7 changed files with 590 additions and 143 deletions

View file

@ -64,6 +64,8 @@ Task List:
* Clean up update script * Clean up update script
* Fix broken themes * Fix broken themes
* Re Add the custom language recognition system after recode * Re Add the custom language recognition system after recode
* Remove all old and unneeded dependencies
* Update all current components to use more current standards ( async await and .then in favor over callbacks )
Completed: Completed:

View file

@ -522,20 +522,30 @@
original: session.untainted, original: session.untainted,
changed: newContent changed: newContent
}, function( success, patch ) { }, function( success, patch ) {
console.log( "diff test", success, patch );
if( success ) { if( success ) {
codiad.filemanager.savePatch( path, patch, session.serverMTime, { if( patch.length > 0 ) {
success: handleSuccess
}, alerts ); codiad.filemanager.save_file( path, {
patch: patch,
mtime: session.serverMTime
}, alerts )
.then( handleSuccess );
}
} else { } else {
codiad.filemanager.saveFile( path, newContent, {
success: handleSuccess console.log( "calling save while failed diff", path, newContent, alerts );
}, alerts ); codiad.filemanager.save_file( path, newContent, alerts )
.then( handleSuccess );
} }
}, this ); }, this );
} else { } else {
codiad.filemanager.saveFile( path, newContent, {
success: handleSuccess console.log( "calling save without mtime and untainted", path, newContent, alerts );
}, alert ); codiad.filemanager.save_file( path, newContent, alerts )
.then( handleSuccess );
} }
}, },

View file

@ -228,7 +228,11 @@
_this.content = content; _this.content = content;
codiad.active.save; codiad.active.save;
codiad.filemanager.saveFile( path, content, localStorage.removeItem( path ), false ); codiad.filemanager.save_file( path, {content: content}, false )
.then( function( i ) {
localStorage.removeItem( path );
});
let session = codiad.active.sessions[path]; let session = codiad.active.sessions[path];
if( typeof session != 'undefined' ) { if( typeof session != 'undefined' ) {

View file

@ -436,7 +436,7 @@ class Filemanager extends Common {
// MODIFY (Modifies a file name/contents or directory name) // MODIFY (Modifies a file name/contents or directory name)
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
public function modify( $path, $content, $patch=false, $mtime=0 ) { public function modify( $path, $content, $patch = false, $mtime = 0 ) {
// Change content // Change content
$response = array( $response = array(
@ -734,12 +734,75 @@ class Filemanager extends Common {
return $response; return $response;
} }
public function stitch( $path ) {
$response = array(
"status" => "none",
"message" => "",
);
if( ! Permissions::has_write( $path ) ) {
$response["status"] = "error";
$response["message"] = "You do not have access to write to this file.";
return $response;
}
if( ! common::isAbsPath( $path ) ) {
$path = WORKSPACE . "/$path";
}
$path = $_POST["path"];
$tmp = DATA . "tmp/$path/";
$dir = dirname( $path );
$name = basename( $path );
$files = scandir( $tmp );
if( ! is_dir( $dir ) ) {
mkdir( $dir, 0755, true );
}
foreach( $files as $id => $file ) {
if( $file !== "." && $file !== ".." ) {
$data = file_get_contents( $cache_path . $file );
$handle = fopen( $path, "a" );
$status = fwrite( $handle, $data );
fclose( $handle );
unlink( $cache_path . $file );
}
}
$tmp_array = explode( "/", $path );
$remove = array();
while( count( $tmp_array ) > 0 ) {
$remove[] = DATA . "tmp/" . implode( "/", $tmp_array );
array_pop( $tmp_array );
}
foreach( $tmp_array as $id => $i ) {
rmdir( $i );
}
return $response;
}
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
// UPLOAD (Handles uploads to the specified directory) // UPLOAD (Handles uploads to the specified directory)
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
public function upload( $path, $blob ) { public function upload( $path, $blob ) {
$response = array(
"status" => "none",
"message" => "",
);
// Check that the path is a directory // Check that the path is a directory
if( ! Permissions::has_write( $path ) ) { if( ! Permissions::has_write( $path ) ) {
@ -753,24 +816,27 @@ class Filemanager extends Common {
$path = WORKSPACE . "/$path"; $path = WORKSPACE . "/$path";
} }
$dirname = dirname( $path );
$name = basename( $path );
$blob = @file_get_contents( $_POST["data"] );
$path = $_POST["path"];
$index = $_POST["index"];
$response = array( $response = array(
"status" => "none", "status" => "none",
"message" => "", "message" => "",
); );
$dirname = dirname( $path ); $tmp = DATA . "tmp/";
$name = basename( $path );
if( ! is_dir( $dirname ) ) { if( ! is_dir( $tmp . $path ) ) {
mkdir( $dirname, 0755, true ); mkdir( $tmp . $path, 0755, true );
} }
$handle = fopen( $path, "a" ); $handle = fopen( "$tmp$path/$index", "a" );
$status = fwrite( $handle, $blob ); $status = fwrite( $handle, $blob );
fclose( $handle ); fclose( $handle );
//$status = file_put_contents( $path, $blob, FILE_APPEND );
if( $status === false ) { if( $status === false ) {
$response["status"] = "error"; $response["status"] = "error";
@ -782,7 +848,6 @@ class Filemanager extends Common {
$response["bytes"] = $status; $response["bytes"] = $status;
$response["message"] = "$status bytes written to file."; $response["message"] = "$status bytes written to file.";
} }
return $response; return $response;
} }
} }

View file

@ -260,6 +260,11 @@ switch( $action ) {
} }
break; break;
case( "stitch" ):
$response = $Filemanager->stitch( $path );
break;
case 'unarchive': case 'unarchive':
if( ! isset( $path ) ) { if( ! isset( $path ) ) {

View file

@ -18,7 +18,7 @@
clipboard: '', clipboard: '',
controller: 'components/filemanager/controller.php', controller: 'components/filemanager/controller.php',
dialog: 'components/filemanager/dialog.php', dialog: 'components/filemanager/dialog.php',
filelist: { file_previewlist: {
audio: [ audio: [
'aac', 'aac',
@ -226,8 +226,8 @@
action: 'create', action: 'create',
type: type, type: type,
path: path path: path
}, })
function( container ) { .then( function( container ) {
$( '#modal-content form' ) $( '#modal-content form' )
.on( 'submit', function( e ) { .on( 'submit', function( e ) {
@ -274,43 +274,45 @@
codiad.modal.load( 400, this.dialog, { codiad.modal.load( 400, this.dialog, {
action: 'delete', action: 'delete',
path: path path: path
}); })
$( '#modal-content form' ) .then( function( container ) {
.live( 'submit', function( e ) {
e.preventDefault(); $( '#modal-content form' )
$.get( _this.controller + '?action=delete&path=' + encodeURIComponent( path ), function( data ) { .on( 'submit', function( e ) {
e.preventDefault();
let response = codiad.jsend.parse( data ); $.get( _this.controller + '?action=delete&path=' + encodeURIComponent( path ), function( data ) {
if( response != 'error' ) {
let node = $( '#file-manager a[data-path="' + path + '"]' ); let response = codiad.jsend.parse( data );
let parent_path = node.parent().parent().children( 'a' ).attr( 'data-path' ); if( response != 'error' ) {
node.parent( 'li' ).remove();
// Close any active files
$( '#active-files a' ).each( function() {
let curPath = $( this ).attr( 'data-path' ); let node = $( '#file-manager a[data-path="' + path + '"]' );
let parent_path = node.parent().parent().children( 'a' ).attr( 'data-path' );
node.parent( 'li' ).remove();
console.log( curPath, curPath.indexOf( path ) ); // Close any active files
$( '#active-files a' ).each( function() {
if( curPath.indexOf( path ) == 0 ) {
codiad.active.remove( curPath ); let curPath = $( this ).attr( 'data-path' );
}
}); console.log( curPath, curPath.indexOf( path ) );
/* Notify listeners. */ if( curPath.indexOf( path ) == 0 ) {
amplify.publish( 'filemanager.onDelete', {
deletePath: path, codiad.active.remove( curPath );
path: parent_path }
}); });
}
codiad.modal.unload(); /* Notify listeners. */
amplify.publish( 'filemanager.onDelete', {
deletePath: path,
path: parent_path
});
}
codiad.modal.unload();
});
}); });
}); })
}, },
delete_children_nodes: function( path ) { delete_children_nodes: function( path ) {
@ -541,6 +543,13 @@
return files; return files;
}, },
get_parent: function( path ) {
let parent = path.split( '/' );
parent.pop();
return parent.join( '/' );
},
get_short_name: function( path ) { get_short_name: function( path ) {
return path.split( '/' ).pop(); return path.split( '/' ).pop();
@ -881,7 +890,7 @@
_this.download( path ); _this.download( path );
} else { } else {
_this.openInModal( path ); _this.open_in_modal( path );
} }
} else { } else {
@ -900,57 +909,77 @@
_this.dialog, _this.dialog,
{ {
action: 'selector', action: 'selector',
}, }
async function( container ) { )
.then( async function( container ) {
let _this = codiad.filemanager;
let div = $( "<div></div>" );
let select = $( '<button class="btn-left">Select</button>' );
let cancel = $( '<button class="btn-right">Cancel</button>' );
if( ! path ) {
let _this = codiad.filemanager; path = codiad.project.getCurrent();
let div = $( "<div></div>" ); }
let select = $( '<button class="btn-left">Select</button>' );
let cancel = $( '<button class="btn-right">Cancel</button>' ); if( Object.keys( filters ).length == 0 ) {
if( ! path ) { filters = {
path = codiad.project.getCurrent(); type: 'directory',
} }
}
_this.selector_listeners( container, filters, callbacks );
let result = await _this.index(
path,
false,
"create",
filters,
directory_callbacks,
file_callbacks,
);
container.html( div );
container.append( select );
container.append( cancel );
select.on( 'click', function( e ) {
if( Object.keys( filters ).length == 0 ) { codiad.modal.unload();
resolve( _this.selected );
filters = { });
cancel.on( 'click', function( e ) {
type: 'directory',
}
}
_this.selector_listeners( container, filters, callbacks ); codiad.modal.unload();
reject({
let result = await _this.index( status: "error",
path, message: "User canceled action."
false,
"create",
filters,
directory_callbacks,
file_callbacks,
);
container.html( div );
container.append( select );
container.append( cancel );
select.on( 'click', function( e ) {
codiad.modal.unload();
resolve( _this.selected );
}); });
cancel.on( 'click', function( e ) { });
})
codiad.modal.unload(); .error( reject );
reject({ });
status: "error", },
message: "User canceled action."
}); open_in_modal: function( path ) {
});
}, let type = "";
); let ext = this.getExtension( path ).toLowerCase();
if( this.file_previewlist.images.includes( ext ) ) {
type = 'music_preview';
} else if( this.file_previewlist.images.includes( ext ) ) {
type = 'preview';
}
codiad.modal.load( 250, this.dialog, {
action: type,
path: path
}); });
}, },
@ -965,8 +994,8 @@
path: path, path: path,
short_name: shortName, short_name: shortName,
type: type type: type
}, })
function( content ) { .then( function( content ) {
$( content ).find( 'form' ) $( content ).find( 'form' )
.on( 'submit', function( e ) { .on( 'submit', function( e ) {
@ -986,6 +1015,165 @@
}); });
}, },
paste_node: function( path ) {
let _this = this;
let overwrite = false;
if( this.clipboard == '' ) {
codiad.message.error( i18n( 'Nothing in Your Clipboard' ) );
} else if( path == this.clipboard ) {
codiad.message.error( i18n( 'Cannot Paste Directory Into Itself' ) );
} else {
let short_name = _this.get_short_name( _this.clipboard );
let new_path = path + '/' + short_name
if( $( '#file-manager a[data-path="' + new_path + '"]' ).length ) {
// Confirm overwrite?
codiad.modal.load( 400, this.dialog, {
action: 'overwrite',
path: new_path
});
$( '#modal-content form' )
.on( 'submit', function( e ) {
e.preventDefault();
codiad.modal.unload();
if( $( '#modal-content form select[name="or_action"]' ).val() == 1 ) {
overwrite = true;
}
$.ajax({
type: 'POST',
url: _this.controller + '?action=copy',
data: {
path: path,
destination: new_path,
overwrite: overwrite,
},
success: async function( data ) {
amplify.publish( 'filemanager.onPaste', {
path: path,
shortName: shortName,
duplicate: duplicate
});
let dir = await _this.is_dir( new_path );
if( dir ) {
_this.rescan( new_path );
} else {
_this.rescan( _this.get_parent( new_path ) );
}
if( path !== new_path ) {
_this.rescan( path );
}
},
error: function( data ) {
console.log( data );
},
});
});
} else {
$.ajax({
type: 'POST',
url: _this.controller + '?action=copy',
data: {
path: path,
destination: new_path,
overwrite: overwrite,
},
success: async function( data ) {
amplify.publish( 'filemanager.onPaste', {
path: path,
shortName: shortName,
duplicate: duplicate
});
let dir = await _this.is_dir( new_path );
if( dir ) {
_this.rescan( new_path );
} else {
_this.rescan( _this.get_parent( new_path ) );
}
if( path !== new_path ) {
_this.rescan( path );
}
},
error: function( data ) {
console.log( data );
},
});
}
}
},
refresh_preview: function( event ) {
let _this = codiad.filemanager;
/**
* When reloading after every change, we encounter performance issues
* in the editor. Therefore, we implement the same logic as the
* auto_save module where we only reload after the user has finished
* changing their document.
*/
if( _this.refresh_interval !== null ) {
clearTimeout( _this.refresh_interval );
_this.refresh_interval = null;
}
_this.refresh_interval = setTimeout( function() {
if( _this.preview == null ) {
return;
}
try {
if( ( typeof _this.preview.location.reload ) == "undefined" ) {
_this.preview = null;
codiad.editor.getActive().removeEventListener( "change", _this.refreshPreview );
return;
}
_this.preview.location.reload( true );
} catch ( e ) {
console.log( e );
codiad.message.error( 'Please close your previously opened preview window.' );
_this.preview = null;
codiad.editor.getActive().removeEventListener( "change", _this.refreshPreview );
}
}, 500 );
},
rename: function( path, new_path ) { rename: function( path, new_path ) {
let _this = codiad.filemanager; let _this = codiad.filemanager;
@ -1083,11 +1271,148 @@
_this.index( path, true ); _this.index( path, true );
}, },
save_file: function() {}, save_file: function( path, data, display_messages = true ) {
return new Promise( function( resolve, reject ) {
let _this = codiad.filemanager;
$.ajax({
type: 'POST',
url: _this.controller + '?action=modify',
data: {
path: path,
data: JSON.stringify( data ),
},
success: function( data ) {
console.log( data );
let r = JSON.parse( data );
if( r.status === "success" ) {
if( display_messages === true ) {
codiad.message.success( i18n( 'File saved' ) );
}
resolve( data );
} else if( r.message == 'Client is out of sync' ) {
let reload = confirm(
"Server has a more updated copy of the file. Would " +
"you like to refresh the contents ? Pressing no will " +
"cause your changes to override the server's copy upon " +
"next save."
);
if( reload ) {
codiad.active.close( path );
codiad.active.removeDraft( path );
_this.openFile( path );
} else {
let session = codiad.editor.getActive().getSession();
session.serverMTime = null;
session.untainted = null;
}
resolve( data );
} else {
codiad.message.error( i18n( r.message ) );
reject( data );
}
},
error: function( data ) {
codiad.message.error( i18n( 'File could not be saved' ) );
reject( data );
},
});
});
},
save_modifications: function() {}, search: async function( path ) {
save_patch: function() {}, let _this = this;
let container = await codiad.modal.load( 500, this.dialog, {
action: 'search',
path: path
});
codiad.modal.hideOverlay();
let last_searched = JSON.parse( await codiad.settings.get_option( "lastSearched" ) );
if( last_searched ) {
$( '#modal-content form input[name="search_string"]' ).val( lastSearched.searchText );
$( '#modal-content form input[name="search_file_type"]' ).val( lastSearched.fileExtension );
$( '#modal-content form select[name="search_type"]' ).val( lastSearched.searchType );
if( lastSearched.searchResults != '' ) {
$( '#filemanager-search-results' ).slideDown().html( lastSearched.searchResults );
}
}
$( '#modal-content form' )
.on( 'submit', function( e ) {
$( '#filemanager-search-processing' ).show();
e.preventDefault();
searchString = $( '#modal-content form input[name="search_string"]' ).val();
fileExtensions = $( '#modal-content form input[name="search_file_type"]' ).val();
searchFileType = $.trim( fileExtensions );
if( searchFileType != '' ) {
//season the string to use in find command
searchFileType = "\\(" + searchFileType.replace( /\s+/g, "\\|" ) + "\\)";
}
searchType = $( '#modal-content form select[name="search_type"]' )
.val();
let options = {
filetype: fileExtensions,
};
$.post( _this.controller + '?action=search', {
path: path,
query: searchString,
options: JSON.stringify( options )
}, function( data ) {
let searchResponse = codiad.jsend.parse( data );
let results = '';
console.log( data );
console.log( searchResponse );
if( searchResponse != 'error' ) {
$.each( searchResponse.index, function( key, val ) {
// Cleanup file format
if( val['file'].substr( -1 ) == '/' ) {
val['file'] = val['file'].substr( 0, str.length - 1 );
}
val['file'] = val['file'].replace( '//', '/' );
// Add result
results += '<div><a onclick="codiad.filemanager.openFile(\'' + val['result'] + '\');setTimeout( function() { codiad.active.gotoLine(' + val['line'] + '); }, 500);codiad.modal.unload();">Line ' + val['line'] + ': ' + val['file'] + '</a></div>';
});
$( '#filemanager-search-results' )
.slideDown()
.html( results );
} else {
$( '#filemanager-search-results' )
.slideUp();
}
codiad.settings.update_option(
"lastSearched",
JSON.stringify({
searchText: searchText,
searchType: searchType,
fileExtension: fileExtensions,
searchResults: searchResults
})
)
_this.saveSearchResults( searchString, searchType, fileExtensions, results );
$( '#filemanager-search-processing' )
.hide();
});
});
},
set_children: function( path, files, children ) { set_children: function( path, files, children ) {
@ -1261,18 +1586,54 @@
upload: function() {}, upload: function() {},
//Compatibility functions upload_to_node: function( path ) {
let _this = codiad.filemanager;
codiad.modal.load(
500,
this.dialog, {
action: 'upload',
}
)
.then( function( container ) {
let text = $( '<p style="max-width: 40vw;"></p>' );
let input = $( '<input type="file" multiple style="display: none;">' );
text.html( `<h2>Drag and drop files or folders anywhere or click here to upload a file!</h2>` );
input.on( 'change', function( e ) {
console.log( e );
let items = e.target.files;
_this.upload( items, path );
});
text.on( 'click', function( e ) {
input.click();
});
container.html( '' );
container.append( text );
container.append( input );
});
},
copyNode: this.copy_node, //Compatibility functions
//these may be needed more after updating the new functions to newer standards
copyNode: function( path ) {return this.copy_node( path )},
createNode: function( path, type ) {return this.create_node( path, type )}, createNode: function( path, type ) {return this.create_node( path, type )},
deleteNode: this.delete_node, deleteNode: function( path ) {return this.delete_node( path )},
getExtension: function( path ) {return this.get_extension( path )}, getExtension: function( path ) {return this.get_extension( path )},
getShortName: function( path ) {return this.get_short_name( path )}, getShortName: function( path ) {return this.get_short_name( path )},
getType: function( path ) {return this.get_type( path )}, getType: function( path ) {return this.get_type( path )},
openFile: function( path ) {return this.open_file( path )}, openFile: function( path ) {return this.open_file( path )},
openInBrowser: this.preview, openInBrowser: function( path ) {return this.preview( path )},
pasteNode: this.paste_node, pasteNode: function( path ) {return this.paste_node( path )},
renameNode: this.rename_node, renameNode: function( path ) {return this.rename_node( path )},
saveFile: this.save_file, saveFile: function( path, data, display_messages ) {return this.save_file( path, data, display_messages )},
uploadToNode: function( path ) {return this.upload_to_node( path )},
}; };
})( this, jQuery ); })( this, jQuery );

View file

@ -19,44 +19,44 @@
.hide(); .hide();
}, },
load: function( width, url, data, callback = null ) { load: function( width, url, data ) {
data = data || {}; return new Promise( function( resolve, reject ) {
let bounds = this._getBounds( width );
let content = $( '#modal-content' )
$('#modal')
.css({
'top': bounds.top,
'left': bounds.left,
'min-width': width + 'px',
'margin-left': '-' + Math.ceil( width / 2 ) + 'px'
})
.draggable({
handle: '#drag-handle'
});
content.html('<div id="modal-loading"></div>');
this.load_process = $.get( url, data, function( data ) {
content.html( data ); data = data || {};
// Fix for Firefox autofocus goofiness let _this = codiad.modal;
$('#modal-content input[autofocus="autofocus"]').focus(); let bounds = _this._getBounds( width );
let content = $( '#modal-content' )
$('#modal')
.css({
'top': bounds.top,
'left': bounds.left,
'min-width': width + 'px',
'margin-left': '-' + Math.ceil( width / 2 ) + 'px'
})
.draggable({
handle: '#drag-handle'
});
content.html('<div id="modal-loading"></div>');
if( callback ) { _this.load_process = $.get( url, data, function( data ) {
callback( content ); content.html( data );
} // Fix for Firefox autofocus goofiness
}); $('#modal-content input[autofocus="autofocus"]').focus();
resolve( content );
let event = {animationPerformed: false}; }).error( reject );
amplify.publish( 'modal.onLoad', event );
// If no plugin has provided a custom load animation
if( ! event.animationPerformed ) {
$('#modal, #modal-overlay').fadeIn(200); let event = {animationPerformed: false};
} amplify.publish( 'modal.onLoad', event );
codiad.sidebars.modalLock = true;
// If no plugin has provided a custom load animation
if( ! event.animationPerformed ) {
$('#modal, #modal-overlay').fadeIn(200);
}
codiad.sidebars.modalLock = true;
});
}, },
show_loading: function() { show_loading: function() {