13 Commits
1.4 ... 1.4.1

Author SHA1 Message Date
Pierre-Olivier Latour
467830e4de Fix 2014-04-02 10:12:27 -07:00
Pierre-Olivier Latour
030c28eb93 Fix 2014-04-02 10:09:07 -07:00
Pierre-Olivier Latour
e4702059c8 #30 Add support for moving files 2014-04-02 10:05:38 -07:00
Pierre-Olivier Latour
877813ed0f Fix 2014-04-02 09:44:18 -07:00
Pierre-Olivier Latour
ccfb4f0b54 Use modal panel instead of prompt() when creating folders 2014-04-02 09:41:07 -07:00
Pierre-Olivier Latour
e27fd601a8 Fix 2014-04-02 09:40:43 -07:00
Pierre-Olivier Latour
7c7f561f90 Fixed default footer for CLTs 2014-04-02 09:02:43 -07:00
Pierre-Olivier Latour
689cb5f26a Fix 2014-04-02 08:50:18 -07:00
Pierre-Olivier Latour
1e4c508737 Update README.md 2014-04-02 08:49:51 -07:00
Pierre-Olivier Latour
ef08ab5516 Update README.md 2014-04-02 08:49:11 -07:00
Pierre-Olivier Latour
18ad23f503 Update README.md 2014-04-02 08:47:32 -07:00
Pierre-Olivier Latour
d68687af62 Fix 2014-04-02 08:34:19 -07:00
Pierre-Olivier Latour
0cdf441830 Update README.md 2014-04-01 16:59:43 -07:00
6 changed files with 136 additions and 11 deletions

View File

@@ -42,6 +42,11 @@
text-align: right;
}
.column-move {
width: 40px;
text-align: center;
}
.column-delete {
width: 40px;
text-align: center;
@@ -64,6 +69,16 @@
float: right;
}
#create-input {
width: 50%;
height: 20px;
}
#move-input {
width: 80%;
height: 20px;
}
/* Bootstrap overrides */
.btn:focus {

View File

@@ -95,12 +95,54 @@
</div>
<div class="modal fade" id="create-modal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title">Create Folder</h4>
</div>
<div class="modal-body">
<p>Please enter the name of the folder to be created:</p>
<form onsubmit="return false">
<input type="text" autocomplete="off" id="create-input">
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" id="create-confirm">Create Folder</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="move-modal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title">Move Item</h4>
</div>
<div class="modal-body">
<p>Please enter the new location for this item:</p>
<form onsubmit="return false">
<input type="text" autocomplete="off" id="move-input">
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" id="move-confirm">Move Item</button>
</div>
</div>
</div>
</div>
<script type="text/x-tmpl" id="template-listing">
<tr class="row-file" data-path="{%=o.path%}" data-name="{%=o.name%}">
<td class="column-icon">
{% if (o.size != null) { %}
<button type="button" class="btn btn-default btn-xs button-download">
<span class="glyphicon glyphicon-download"></span>
<span class="glyphicon glyphicon-download-alt"></span>
</button>
{% } else { %}
<button type="button" class="btn btn-default btn-xs button-open">
@@ -114,6 +156,11 @@
<p>{%=formatFileSize(o.size)%}</p>
{% } %}
</td>
<td class="column-move">
<button type="button" class="btn btn-default btn-xs button-move">
<span class="glyphicon glyphicon glyphicon-share-alt"></span>
</button>
</td>
<td class="column-delete">
<button type="button" class="btn btn-danger btn-xs button-delete">
<span class="glyphicon glyphicon-trash"></span>
@@ -132,7 +179,7 @@
<td class="column-path"><p>{%=o.path%}</p></td>
<td class="column-progress">
<div class="progress">
<div class="progress-bar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" id="progress-bar"></div>
<div class="progress-bar" id="progress-bar"></div>
</div>
</ts>
</tr>
@@ -140,7 +187,7 @@
<script type="text/x-tmpl" id="template-alert">
<div class="alert alert-{%=o.level%} alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
<button type="button" class="close" data-dismiss="alert">&times;</button>
<strong>{%=o.title%}</strong>{%=o.description%}
</div>
</script>

View File

@@ -122,6 +122,16 @@ function _reload(path) {
_reload(path);
});
$(".button-move").click(function(event) {
var path = $(this).parent().parent().attr("data-path");
if (path[path.length - 1] == "/") {
path = path.slice(0, path.length - 1);
}
$("#move-input").attr("data-path", path);
$("#move-input").val(path);
$("#move-modal").modal("show");
});
$(".button-delete").click(function(event) {
var path = $(this).parent().parent().attr("data-path");
$.ajax({
@@ -202,9 +212,20 @@ $(document).ready(function() {
});
$("#create-modal").on("shown.bs.modal", function(event) {
$("#create-input").focus();
$("#create-input").select();
})
$("#create-folder").click(function(event) {
var name = prompt("Please enter folder name:", "Untitled folder");
if ((name != null) && (name != "")) {
$("#create-input").val("Untitled folder");
$("#create-modal").modal("show");
});
$("#create-confirm").click(function(event) {
$("#create-modal").modal("hide");
var name = $("#create-input").val();
if (name != "") {
$.ajax({
url: 'create',
type: 'POST',
@@ -218,6 +239,29 @@ $(document).ready(function() {
}
});
$("#move-modal").on("shown.bs.modal", function(event) {
$("#move-input").focus();
$("#move-input").select();
})
$("#move-confirm").click(function(event) {
$("#move-modal").modal("hide");
var oldPath = $("#move-input").attr("data-path");
var newPath = $("#move-input").val();
if ((newPath != "") && (newPath[0] == "/") && (newPath != oldPath)) {
$.ajax({
url: 'move',
type: 'POST',
data: {oldPath: oldPath, newPath: newPath},
dataType: 'json'
}).fail(function(jqXHR, textStatus, errorThrown) {
_showError("Failed moving \"" + oldPath + "\" to \"" + newPath + "\"", textStatus, errorThrown);
}).always(function() {
_reload(_path);
});
}
});
$("#reload").click(function(event) {
_reload(_path);
});

View File

@@ -46,7 +46,7 @@
@property(nonatomic, copy) NSString* title; // Default is application name (must be HTML escaped)
@property(nonatomic, copy) NSString* header; // Default is same as title (must be HTML escaped)
@property(nonatomic, copy) NSString* prologue; // Default is mini help (must be raw HTML)
@property(nonatomic, copy) NSString* epilogue; // Default is mini help (must be raw HTML)
@property(nonatomic, copy) NSString* epilogue; // Default is nothing (must be raw HTML)
@property(nonatomic, copy) NSString* footer; // Default is application name and version (must be HTML escaped)
- (id)initWithUploadDirectory:(NSString*)path;
@end

View File

@@ -88,7 +88,11 @@
return nil;
}
_uploadDirectory = [[path stringByStandardizingPath] copy];
GCDWebUploader* __unsafe_unretained uploader = self; // Avoid retain-cycles with self
#if __has_feature(objc_arc)
__unsafe_unretained GCDWebUploader* uploader = self;
#else
__block GCDWebUploader* uploader = self;
#endif
// Resource files
[self addGETHandlerForBasePath:@"/" directoryPath:[siteBundle resourcePath] indexFilename:nil cacheAge:3600 allowRangeRequests:NO];
@@ -108,6 +112,11 @@
NSString* title = uploader.title;
if (title == nil) {
title = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
#if !TARGET_OS_IPHONE
if (title == nil) {
title = [[NSProcessInfo processInfo] processName];
}
#endif
}
NSString* header = uploader.header;
if (header == nil) {
@@ -123,9 +132,15 @@
}
NSString* footer = uploader.footer;
if (footer == nil) {
footer = [NSString stringWithFormat:[siteBundle localizedStringForKey:@"FOOTER_FORMAT" value:@"" table:nil],
[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"],
[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]];
NSString* name = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
NSString* version = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
#if !TARGET_OS_IPHONE
if (!name && !version) {
name = @"OS X";
version = [[NSProcessInfo processInfo] operatingSystemVersionString];
}
#endif
footer = [NSString stringWithFormat:[siteBundle localizedStringForKey:@"FOOTER_FORMAT" value:@"" table:nil], name, version];
}
return [GCDWebServerDataResponse responseWithHTMLTemplate:[siteBundle pathForResource:@"index" ofType:@"html"]
variables:@{

View File

@@ -10,6 +10,9 @@ GCDWebServer is a lightweight GCD based HTTP 1.1 server designed to be embedded
* No dependencies on third-party source code
* Available under a friendly [New BSD License](LICENSE)
Included extensions:
* [GCDWebUploader](GCDWebUploader/GCDWebUploader.h): subclass of GCDWebServer that implements an interface for uploading and downloading files from an iOS app's sandbox using a web browser
What's not available out of the box but can be implemented on top of the API:
* Authentication like [Basic Authentication](https://en.wikipedia.org/wiki/Basic_access_authentication)
* Web forms submitted using "multipart/mixed"
@@ -70,6 +73,7 @@ Simply instantiate and run a GCDWebUploader instance then visit http://{YOUR-IOS
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
GCDWebUploader* webUploader = [[GCDWebUploader alloc] initWithUploadDirectory:documentsPath];
[webUploader start];
NSLog(@"Visit %@ in your web browser", webUploader.serverURL);
return YES;
}
```
@@ -222,4 +226,4 @@ Final Example: File Downloads and Uploads From iOS App
GCDWebServer was originally written for the [ComicFlow](http://itunes.apple.com/us/app/comicflow/id409290355?mt=8) comic reader app for iPad. It uses it to provide a web server for people to upload and download comic files directly over WiFi to and from the app.
ComicFlow is [entirely open-source](https://github.com/swisspol/ComicFlow) and you can see how it uses GCDWebServer in the [WebServer.m](https://github.com/swisspol/ComicFlow/blob/master/Classes/WebServer.m) file.
ComicFlow is [entirely open-source](https://github.com/swisspol/ComicFlow) and you can see how it uses GCDWebUploader in the [WebServer.m](https://github.com/swisspol/ComicFlow/blob/master/Classes/WebServer.m) file.