File adding support, editor enhancements, JS improved.

This commit is contained in:
Dane Everitt 2016-10-03 20:22:28 -04:00
parent 50b377d08c
commit 81dc74a175
No known key found for this signature in database
GPG key ID: EEA66103B3D71F53
4 changed files with 83 additions and 41 deletions

View file

@ -136,7 +136,7 @@ class FileRepository
*
* @param string $file
* @param string $content
* @return boolean
* @return bool
*/
public function saveFileContents($file, $content)
{
@ -149,23 +149,6 @@ class FileRepository
$file->dirname = (in_array($file->dirname, ['.', './', '/'])) ? null : trim($file->dirname, '/') . '/';
$res = $this->client->request('GET', '/server/files/stat/' . rawurlencode($file->dirname.$file->basename) , [
'headers' => $this->headers
]);
$stat = json_decode($res->getBody());
if($res->getStatusCode() !== 200 || !isset($stat->size)) {
throw new DisplayException('The daemon provided a non-200 error code on stat lookup: HTTP\\' . $res->getStatusCode());
}
if (!in_array($stat->mime, HelperRepository::editableFiles())) {
throw new DisplayException('You cannot edit that type of file (' . $stat->mime . ') through the panel.');
}
if ($stat->size > 5000000) {
throw new DisplayException('That file is too large to save in the browser, consider using a SFTP client.');
}
$res = $this->client->request('POST', '/server/file/' . rawurlencode($file->dirname.$file->basename), [
'headers' => $this->headers,
'json' => [

View file

@ -40,14 +40,44 @@
<form method="post" id="new_file">
<h4>/home/container/{{ $directory }} <input type="text" id="file_name" class="filename" value="newfile.txt" /></h4>
<div class="form-group">
<div>
<textarea name="file_contents" id="fileContents" style="border: 1px solid #dddddd;" class="form-control console"></textarea>
</div>
<div id="fileContents" style="height:500px;"></div>
</div>
<div class="form-group">
<div>
<button class="btn btn-primary btn-sm" id="create_file">{{ trans('strings.save') }}</button>
<button class="btn btn-default btn-sm" onclick="window.location='/server/{{ $server->uuidShort }}/files?dir=/{{ $directory }}';return false;">{{ trans('server.files.back') }}</button>
<div class="row">
<div class="col-md-8">
<button class="btn btn-primary btn-sm" id="create_file">{{ trans('strings.save') }}</button>
<button class="btn btn-default btn-sm" onclick="window.location='/server/{{ $server->uuidShort }}/files?dir=/{{ $directory }}';return false;">{{ trans('server.files.back') }}</button>
</div>
<div class="col-md-4 pull-right">
<select name="aceMode" id="aceMode" class="form-control">
<option value="assembly_x86">Assembly x86</option>
<option value="c_cpp">C/C++</option>
<option value="coffee">CoffeeScript</option>
<option value="csharp">C#</option>
<option value="css">CSS</option>
<option value="golang">Go</option>
<option value="haml">HAML</option>
<option value="html">HTML</option>
<option value="ini">INI</option>
<option value="java">Java</option>
<option value="javascript">JavaScript</option>
<option value="json">JSON</option>
<option value="lua">Lua</option>
<option value="markdown">Markdown</option>
<option value="mysql">MySQL</option>
<option value="objectivec">Objective-C</option>
<option value="perl">Perl</option>
<option value="php">PHP</option>
<option value="properties">Properties</option>
<option value="python">Python</option>
<option value="ruby">Ruby</option>
<option value="rust">Rust</option>
<option value="smarty">Smarty</option>
<option value="textile" selected="selected">Plain Text</option>
<option value="xml">XML</option>
<option value="yaml">YAML</option>
</select>
</div>
</div>
</div>
</form>
@ -66,6 +96,8 @@
@endcan
</div>
</div>
{!! Theme::js('js/vendor/ace/ace.js') !!}
{!! Theme::js('js/vendor/ace/ext-modelist.js') !!}
<script>
$(window).load(function () {
@ -170,35 +202,54 @@ $(window).load(function () {
}
@endcan
$('textarea').keydown(function (e) {
if (e.keyCode === 9) {
var start = this.selectionStart;
var end = this.selectionEnd;
var value = $(this).val();
$(this).val(value.substring(0, start) + '\t' + value.substring(end));
this.selectionStart = this.selectionEnd = start + 1;
e.preventDefault();
}
const Editor = ace.edit('fileContents');
Editor.setTheme('ace/theme/chrome');
Editor.getSession().setUseWrapMode(true);
Editor.setShowPrintMargin(false);
$('#aceMode').on('change', event => {
Editor.getSession().setMode(`ace/mode/${$('#aceMode').val()}`);
});
$("#create_file").click(function(e) {
Editor.commands.addCommand({
name: 'save',
bindKey: {win: 'Ctrl-S', mac: 'Command-S'},
exec: function(editor) {
save();
},
readOnly: false
});
$('#create_file').on('click', function (e) {
e.preventDefault();
$("#create_file").append(' <i class="fa fa-spinner fa fa-spin"></i>').addClass("disabled");
save();
});
function save() {
var fileName = $('input[name="file"]').val();
$('#create_file').append(' <i class="fa fa-spinner fa fa-spin"></i>').addClass('disabled');
$.ajax({
type: 'POST',
url: '{{ route('server.files.save', $server->uuidShort) }}',
headers: { 'X-CSRF-Token': '{{ csrf_token() }}' },
data: {
file: '{{ $directory }}' + $('#file_name').val(),
contents: $('#fileContents').val()
contents: Editor.getValue()
}
}).done(function (data) {
window.location.replace('/server/{{ $server->uuidShort }}/files/edit/{{ $directory }}' + $('#file_name').val());
}).fail(function (jqXHR) {
$('#write_status').html('<div class="alert alert-danger">' + jqXHR.responseText + '</div>').show();
$('#create_file').html('{{ trans('strings.save') }}').removeClass('disabled');
$.notify({
message: jqXHR.responseText
}, {
type: 'danger'
});
}).always(function () {
$('#save_file').html('{{ trans('strings.save') }}').removeClass('disabled');
});
});
}
});
</script>

View file

@ -50,7 +50,7 @@ $(document).ready(function () {
const Editor = ace.edit('editor');
const Modelist = ace.require('ace/ext/modelist')
Editor.setTheme('ace/theme/github');
Editor.setTheme('ace/theme/chrome');
Editor.getSession().setMode(Modelist.getModeForPath('{{ $stat->name }}').mode);
Editor.getSession().setUseWrapMode(true);
Editor.setShowPrintMargin(false);

View file

@ -99,7 +99,11 @@ class ActionsClass {
inputField.focus();
inputField.on('blur keypress', e => {
// Save Field
if (e.type === 'blur' || (e.type === 'keypress' && e.which === 27) || currentName === inputField.val()) {
if (
(e.type === 'keypress' && e.which === 27)
|| e.type === 'blur'
|| (e.type === 'keypress' && e.which === 13 && currentName === inputField.val())
) {
if (!_.isEmpty(currentLink)) {
nameBlock.html(currentLink);
} else {
@ -110,6 +114,10 @@ class ActionsClass {
return;
}
if (e.type === 'keypress' && e.which !== 13) return;
console.log('did not');
inputLoader.show();
const currentPath = decodeURIComponent(nameBlock.data('path'));