File adding support, editor enhancements, JS improved.
This commit is contained in:
parent
50b377d08c
commit
81dc74a175
4 changed files with 83 additions and 41 deletions
|
@ -136,7 +136,7 @@ class FileRepository
|
||||||
*
|
*
|
||||||
* @param string $file
|
* @param string $file
|
||||||
* @param string $content
|
* @param string $content
|
||||||
* @return boolean
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function saveFileContents($file, $content)
|
public function saveFileContents($file, $content)
|
||||||
{
|
{
|
||||||
|
@ -149,23 +149,6 @@ class FileRepository
|
||||||
|
|
||||||
$file->dirname = (in_array($file->dirname, ['.', './', '/'])) ? null : trim($file->dirname, '/') . '/';
|
$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), [
|
$res = $this->client->request('POST', '/server/file/' . rawurlencode($file->dirname.$file->basename), [
|
||||||
'headers' => $this->headers,
|
'headers' => $this->headers,
|
||||||
'json' => [
|
'json' => [
|
||||||
|
|
|
@ -40,14 +40,44 @@
|
||||||
<form method="post" id="new_file">
|
<form method="post" id="new_file">
|
||||||
<h4>/home/container/{{ $directory }} <input type="text" id="file_name" class="filename" value="newfile.txt" /></h4>
|
<h4>/home/container/{{ $directory }} <input type="text" id="file_name" class="filename" value="newfile.txt" /></h4>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div>
|
<div id="fileContents" style="height:500px;"></div>
|
||||||
<textarea name="file_contents" id="fileContents" style="border: 1px solid #dddddd;" class="form-control console"></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div>
|
<div class="row">
|
||||||
<button class="btn btn-primary btn-sm" id="create_file">{{ trans('strings.save') }}</button>
|
<div class="col-md-8">
|
||||||
<button class="btn btn-default btn-sm" onclick="window.location='/server/{{ $server->uuidShort }}/files?dir=/{{ $directory }}';return false;">{{ trans('server.files.back') }}</button>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -66,6 +96,8 @@
|
||||||
@endcan
|
@endcan
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{!! Theme::js('js/vendor/ace/ace.js') !!}
|
||||||
|
{!! Theme::js('js/vendor/ace/ext-modelist.js') !!}
|
||||||
<script>
|
<script>
|
||||||
$(window).load(function () {
|
$(window).load(function () {
|
||||||
|
|
||||||
|
@ -170,35 +202,54 @@ $(window).load(function () {
|
||||||
}
|
}
|
||||||
@endcan
|
@endcan
|
||||||
|
|
||||||
$('textarea').keydown(function (e) {
|
const Editor = ace.edit('fileContents');
|
||||||
if (e.keyCode === 9) {
|
|
||||||
var start = this.selectionStart;
|
Editor.setTheme('ace/theme/chrome');
|
||||||
var end = this.selectionEnd;
|
Editor.getSession().setUseWrapMode(true);
|
||||||
var value = $(this).val();
|
Editor.setShowPrintMargin(false);
|
||||||
$(this).val(value.substring(0, start) + '\t' + value.substring(end));
|
|
||||||
this.selectionStart = this.selectionEnd = start + 1;
|
$('#aceMode').on('change', event => {
|
||||||
e.preventDefault();
|
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();
|
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({
|
$.ajax({
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
url: '{{ route('server.files.save', $server->uuidShort) }}',
|
url: '{{ route('server.files.save', $server->uuidShort) }}',
|
||||||
headers: { 'X-CSRF-Token': '{{ csrf_token() }}' },
|
headers: { 'X-CSRF-Token': '{{ csrf_token() }}' },
|
||||||
data: {
|
data: {
|
||||||
file: '{{ $directory }}' + $('#file_name').val(),
|
file: '{{ $directory }}' + $('#file_name').val(),
|
||||||
contents: $('#fileContents').val()
|
contents: Editor.getValue()
|
||||||
}
|
}
|
||||||
}).done(function (data) {
|
}).done(function (data) {
|
||||||
window.location.replace('/server/{{ $server->uuidShort }}/files/edit/{{ $directory }}' + $('#file_name').val());
|
window.location.replace('/server/{{ $server->uuidShort }}/files/edit/{{ $directory }}' + $('#file_name').val());
|
||||||
}).fail(function (jqXHR) {
|
}).fail(function (jqXHR) {
|
||||||
$('#write_status').html('<div class="alert alert-danger">' + jqXHR.responseText + '</div>').show();
|
$.notify({
|
||||||
$('#create_file').html('{{ trans('strings.save') }}').removeClass('disabled');
|
message: jqXHR.responseText
|
||||||
|
}, {
|
||||||
|
type: 'danger'
|
||||||
|
});
|
||||||
|
}).always(function () {
|
||||||
|
$('#save_file').html('{{ trans('strings.save') }}').removeClass('disabled');
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -50,7 +50,7 @@ $(document).ready(function () {
|
||||||
const Editor = ace.edit('editor');
|
const Editor = ace.edit('editor');
|
||||||
const Modelist = ace.require('ace/ext/modelist')
|
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().setMode(Modelist.getModeForPath('{{ $stat->name }}').mode);
|
||||||
Editor.getSession().setUseWrapMode(true);
|
Editor.getSession().setUseWrapMode(true);
|
||||||
Editor.setShowPrintMargin(false);
|
Editor.setShowPrintMargin(false);
|
||||||
|
|
|
@ -99,7 +99,11 @@ class ActionsClass {
|
||||||
inputField.focus();
|
inputField.focus();
|
||||||
inputField.on('blur keypress', e => {
|
inputField.on('blur keypress', e => {
|
||||||
// Save Field
|
// 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)) {
|
if (!_.isEmpty(currentLink)) {
|
||||||
nameBlock.html(currentLink);
|
nameBlock.html(currentLink);
|
||||||
} else {
|
} else {
|
||||||
|
@ -110,6 +114,10 @@ class ActionsClass {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (e.type === 'keypress' && e.which !== 13) return;
|
||||||
|
|
||||||
|
console.log('did not');
|
||||||
|
|
||||||
inputLoader.show();
|
inputLoader.show();
|
||||||
const currentPath = decodeURIComponent(nameBlock.data('path'));
|
const currentPath = decodeURIComponent(nameBlock.data('path'));
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue