#20761: Improved media upload experience in Orchard.Azure.MediaServices (added ability for user to control the name of the uploaded file).

Work Item: 20761
This commit is contained in:
Daniel Stolt
2014-06-28 17:55:07 +02:00
parent a884048709
commit 300ef6f71b
12 changed files with 286 additions and 128 deletions

View File

@@ -553,6 +553,30 @@
<ItemGroup>
<Content Include="Scripts\lib\MPEG Dash Notice.docx" />
</ItemGroup>
<ItemGroup>
<Content Include="Styles\cloudmedia-edit-cloudvideopart.css.map">
<DependentUpon>cloudmedia-edit-cloudvideopart.css</DependentUpon>
</Content>
</ItemGroup>
<ItemGroup>
<Content Include="Scripts\cloudmedia-admin-common.js.map" />
<Content Include="Scripts\cloudmedia-admin-job.js.map" />
<Content Include="Scripts\cloudmedia-admin-settings.js.map" />
<Content Include="Scripts\cloudmedia-autorefresh.js.map" />
<Content Include="Scripts\cloudmedia-edit-asset-video.js.map" />
<Content Include="Scripts\cloudmedia-edit-asset.js.map" />
<Content Include="Scripts\cloudmedia-edit-cloudvideopart-direct.js.map" />
<Content Include="Scripts\cloudmedia-edit-cloudvideopart-proxied.js.map" />
<Content Include="Scripts\cloudmedia-edit-cloudvideopart.js.map" />
<Content Include="Scripts\cloudmedia-metadata-cloudvideopart.js.map" />
<Content Include="Scripts\cloudmedia-videoplayer-data.js.map" />
<Content Include="Scripts\cloudmedia-videoplayer-injectors-alt.js.map" />
<Content Include="Scripts\cloudmedia-videoplayer-injectors-dash.js.map" />
<Content Include="Scripts\cloudmedia-videoplayer-injectors-html5.js.map" />
<Content Include="Scripts\cloudmedia-videoplayer-injectors-smp.js.map" />
<Content Include="Scripts\cloudmedia-videoplayer-injectors.js.map" />
<Content Include="Scripts\cloudmedia-videoplayer-main.js.map" />
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
@@ -601,7 +625,7 @@
<IISUrl>
</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>True</UseCustomServer>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>http://orchard.codeplex.com</CustomServerUrl>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>

View File

@@ -27,10 +27,10 @@ var Orchard;
return;
}
var originalFileName = data.files[0].name;
var editedFileName = scope.find("input[name$='.FileName']").val();
var statusUploaded = scope.find(".status.uploaded").show();
statusUploaded.text(statusUploaded.data("text-template").replace("{filename}", originalFileName));
statusUploaded.text(statusUploaded.data("text-template").replace("{filename}", editedFileName));
scope.data("upload-isactive", false);
scope.data("upload-iscompleted", true);
scope.data("upload-start-time", null);
@@ -40,7 +40,7 @@ var Orchard;
var wamsAssetInput = scope.find("input[name$='.WamsAssetId']");
var fileNameInput = scope.find("input[name$='.FileName']");
var assetId = $.trim(wamsAssetInput.val());
var wrapper = data.fileInput.closest(".file-upload-wrapper");
var fileUploadWrapper = data.fileInput.closest(".file-upload-wrapper");
if (assetId.length > 0) {
var url = scope.data("delete-asset-url");
@@ -69,7 +69,7 @@ var Orchard;
});
}
wrapper.show();
fileUploadWrapper.show();
}
function pad(value, length) {
@@ -156,24 +156,35 @@ var Orchard;
return flag;
}
var isSubmitting = function () {
function isSubmitting() {
var scope = $(".upload-direct");
return scope.data("is-submitting") == true;
};
}
;
function initializeUpload(fileInput) {
var scope = fileInput.closest(".async-upload");
var acceptFileTypes = scope.data("upload-accept-file-types");
var fileUploadWrapper = scope.find(".file-upload-wrapper");
var acceptFileTypesRegex = new RegExp(scope.data("upload-accept-file-types"));
var antiForgeryToken = scope.closest("form").find("[name='__RequestVerificationToken']").val();
var selectedFileWrapper = scope.find(".selected-file-wrapper");
var filenameInput = scope.find(".filename-input");
var resetButton = scope.find(".reset-button");
var uploadButton = scope.find(".upload-button");
var filenameText = scope.find(".filename-text");
var validationText = scope.find(".validation-text");
var preparingText = scope.find(".status.preparing");
var uploadingContainer = scope.find(".status.uploading");
var progressBar = scope.find(".progress-bar");
var progressText = scope.find(".progress-text");
var progressDetails = scope.find(".progress-details");
var cancelLink = scope.find(".cancel-link");
fileInput.fileupload({
autoUpload: false,
acceptFileTypes: new RegExp(acceptFileTypes, "i"),
acceptFileTypes: acceptFileTypesRegex,
type: "PUT",
maxChunkSize: 4 * 1024 * 1024,
beforeSend: function (xhr, data) {
@@ -201,7 +212,7 @@ var Orchard;
var uploaded = Math.floor(data.loaded / 1000);
var total = Math.floor(data.total / 1000);
scope.find(".progress-bar").show().find('.progress').css('width', percentComplete + '%');
progressBar.show().find(".progress").css("width", percentComplete + "%");
progressText.text(progressText.data("text-template").replace("{percentage}", percentComplete)).show();
progressDetails.text(progressDetails.data("text-template").replace("{uploaded}", uploaded).replace("{total}", total).replace("{kbps}", kbps).replace("{elapsed}", elapsed.humanize()).replace("{remaining}", remaining.humanize())).show();
},
@@ -215,49 +226,78 @@ var Orchard;
uploadCompleted(this, e, data);
},
processdone: function (e, data) {
scope.find(".validation-text").hide();
var selectedFilename = data.files[0].name;
scope.data("selected-filename", selectedFilename);
window.setTimeout(function () {
fileUploadWrapper.hide();
validationText.hide();
selectedFileWrapper.show();
filenameText.text(filenameText.data("text-template").replace("{filename}", selectedFilename));
}, 10);
var filename = data.files[0].name;
scope.data("upload-isactive", true);
scope.data("upload-start-time", Date.now());
var generateAssetUrl = scope.data("generate-asset-url");
preparingText.show();
scope.find(".file-upload-wrapper").hide();
scope.data("block-index", 0);
scope.data("block-ids", new Array());
scope[0].doReset = function () {
fileUploadWrapper.show();
filenameInput.val("");
filenameText.text("");
selectedFileWrapper.hide();
validationText.hide();
};
$.ajax({
url: generateAssetUrl,
data: {
filename: filename,
__RequestVerificationToken: antiForgeryToken
},
type: "POST"
}).done(function (asset) {
data.url = asset.sasLocator;
data.multipart = false;
scope[0].doUpload = function () {
var editedFilename = filenameInput.val() || selectedFilename;
if (!acceptFileTypesRegex.test(editedFilename)) {
validationText.show();
return;
}
scope.data("sas-locator", asset.sasLocator);
scope.find("input[name$='.FileName']").val(filename);
scope.find("input[name$='.WamsAssetId']").val(asset.assetId);
scope.data("upload-isactive", true);
scope.data("upload-start-time", Date.now());
var generateAssetUrl = scope.data("generate-asset-url");
scope.data("block-index", 0);
scope.data("block-ids", new Array());
preparingText.hide();
progressText.text(progressText.data("text-template").replace("{percentage}", 0)).show();
uploadingContainer.show();
preparingText.show();
selectedFileWrapper.hide();
validationText.hide();
var xhr = data.submit();
scope.data("xhr", xhr);
}).fail(function (xhr, status, error) {
preparingText.hide();
uploadingContainer.hide();
scope.data("upload-isactive", false);
scope.data("upload-start-time", null);
scope.find(".file-upload-wrapper").show();
alert("An error occurred. Error: " + error);
});
$.ajax({
url: generateAssetUrl,
data: {
filename: editedFilename,
__RequestVerificationToken: antiForgeryToken
},
type: "POST"
}).done(function (asset) {
data.url = asset.sasLocator;
data.multipart = false;
scope.data("sas-locator", asset.sasLocator);
scope.find("input[name$='.FileName']").val(editedFilename);
scope.find("input[name$='.WamsAssetId']").val(asset.assetId);
preparingText.hide();
progressText.text(progressText.data("text-template").replace("{percentage}", 0)).show();
uploadingContainer.show();
var xhr = data.submit();
scope.data("xhr", xhr);
}).fail(function (xhr, status, error) {
fileUploadWrapper.show();
selectedFileWrapper.show();
preparingText.hide();
uploadingContainer.hide();
scope.data("upload-isactive", false);
scope.data("upload-start-time", null);
alert("An error occurred. Error: " + error);
});
};
},
processfail: function (e, data) {
scope.find(".validation-text").show();
validationText.show();
filenameInput.val("");
filenameText.text("");
selectedFileWrapper.hide();
},
change: function (e, data) {
var prompt = fileInput.data("prompt");
@@ -272,7 +312,7 @@ var Orchard;
cancelLink.on("click", function (e) {
e.preventDefault();
if (confirm($(this).data("prompt"))) {
if (confirm($(this).data("cancel-prompt"))) {
var xhr = scope.data("xhr");
xhr.abort();
}
@@ -281,9 +321,22 @@ var Orchard;
function initializeUploadDirect() {
var scope = $(".upload-direct").show();
scope.find(".reset-button").on("click", function (e) {
var doReset = $(this).closest(".async-upload")[0].doReset;
if (!!doReset)
doReset();
});
scope.find(".upload-button").on("click", function (e) {
var doUpload = $(this).closest(".async-upload")[0].doUpload;
if (!!doUpload)
doUpload();
});
requiredUploads = scope.find(".required-upload");
scope.find(".async-upload-input").each(function () {
scope.find(".async-upload-file-input").each(function () {
initializeUpload($(this));
});
@@ -297,10 +350,13 @@ var Orchard;
scope.data("is-submitting", true);
});
window.onbeforeunload = function (e) {
if ((hasActiveUploads() || hasCompletedUploads()) && !isSubmitting())
e.returnValue = scope.data("navigate-away-prompt");
};
$(window).on("beforeunload", function (e) {
if ((hasActiveUploads() || hasCompletedUploads()) && !isSubmitting()) {
var message = scope.data("navigate-away-prompt");
e.result = message;
return message;
}
});
}
CloudVideoEdit.initializeUploadDirect = initializeUploadDirect;
})(MediaServices.CloudVideoEdit || (MediaServices.CloudVideoEdit = {}));

View File

@@ -4,7 +4,7 @@
module Orchard.Azure.MediaServices.CloudVideoEdit {
var requiredUploads: JQuery;
function uploadCompleted(sender, e, data) {
var scope = $(sender).closest(".async-upload");
var status = data.errorThrown && data.errorThrown.length > 0 ? data.errorThrown : data.textStatus;
@@ -24,10 +24,10 @@ module Orchard.Azure.MediaServices.CloudVideoEdit {
return;
}
var originalFileName = data.files[0].name;
var editedFileName = scope.find("input[name$='.FileName']").val();
var statusUploaded = scope.find(".status.uploaded").show();
statusUploaded.text(statusUploaded.data("text-template").replace("{filename}", originalFileName));
statusUploaded.text(statusUploaded.data("text-template").replace("{filename}", editedFileName));
scope.data("upload-isactive", false);
scope.data("upload-iscompleted", true);
scope.data("upload-start-time", null);
@@ -37,7 +37,7 @@ module Orchard.Azure.MediaServices.CloudVideoEdit {
var wamsAssetInput = scope.find("input[name$='.WamsAssetId']");
var fileNameInput = scope.find("input[name$='.FileName']");
var assetId = $.trim(wamsAssetInput.val());
var wrapper = data.fileInput.closest(".file-upload-wrapper");
var fileUploadWrapper = data.fileInput.closest(".file-upload-wrapper");
if (assetId.length > 0) {
var url = scope.data("delete-asset-url");
@@ -57,16 +57,16 @@ module Orchard.Azure.MediaServices.CloudVideoEdit {
__RequestVerificationToken: antiForgeryToken
}
}).done(function () {
scope.data("upload-isactive", false);
scope.data("upload-start-time", null);
scope.find(".file-upload-wrapper").show();
cleanupMessage.hide();
}).fail(function () {
alert("An error occurred on the server while trying to clean up.");
});
scope.data("upload-isactive", false);
scope.data("upload-start-time", null);
scope.find(".file-upload-wrapper").show();
cleanupMessage.hide();
}).fail(function () {
alert("An error occurred on the server while trying to clean up.");
});
}
wrapper.show();
fileUploadWrapper.show();
}
function pad(value: number, length: number) {
@@ -151,26 +151,36 @@ module Orchard.Azure.MediaServices.CloudVideoEdit {
});
return flag;
}
}
var isSubmitting = function () {
function isSubmitting() {
var scope = $(".upload-direct");
return scope.data("is-submitting") == true;
};
function initializeUpload(fileInput: JQuery) {
var scope = fileInput.closest(".async-upload");
var acceptFileTypes: string = scope.data("upload-accept-file-types");
var fileUploadWrapper = scope.find(".file-upload-wrapper");
var acceptFileTypesRegex = new RegExp(scope.data("upload-accept-file-types"));
var antiForgeryToken: string = scope.closest("form").find("[name='__RequestVerificationToken']").val();
var selectedFileWrapper = scope.find(".selected-file-wrapper");
var filenameInput = scope.find(".filename-input");
var resetButton = scope.find(".reset-button");
var uploadButton = scope.find(".upload-button");
var filenameText = scope.find(".filename-text");
var validationText = scope.find(".validation-text");
var preparingText = scope.find(".status.preparing");
var uploadingContainer = scope.find(".status.uploading");
var progressBar = scope.find(".progress-bar");
var progressText = scope.find(".progress-text");
var progressDetails = scope.find(".progress-details");
var cancelLink = scope.find(".cancel-link");
var cancelLink = scope.find(".cancel-link");
(<any>fileInput).fileupload({
autoUpload: false,
acceptFileTypes: new RegExp(acceptFileTypes, "i"),
acceptFileTypes: acceptFileTypesRegex,
type: "PUT",
maxChunkSize: 4 * 1024 * 1024, // 4 MB
beforeSend: (xhr: JQueryXHR, data) => {
@@ -198,7 +208,7 @@ module Orchard.Azure.MediaServices.CloudVideoEdit {
var uploaded = Math.floor(data.loaded / 1000);
var total = Math.floor(data.total / 1000);
scope.find(".progress-bar").show().find('.progress').css('width', percentComplete + '%');
progressBar.show().find(".progress").css("width", percentComplete + "%");
progressText.text(progressText.data("text-template").replace("{percentage}", percentComplete)).show();
progressDetails.text(progressDetails.data("text-template").replace("{uploaded}", uploaded).replace("{total}", total).replace("{kbps}", kbps).replace("{elapsed}", elapsed.humanize()).replace("{remaining}", remaining.humanize())).show();
},
@@ -212,49 +222,78 @@ module Orchard.Azure.MediaServices.CloudVideoEdit {
uploadCompleted(this, e, data);
},
processdone: function (e, data) {
scope.find(".validation-text").hide();
var selectedFilename = data.files[0].name;
scope.data("selected-filename", selectedFilename);
window.setTimeout(function () {
fileUploadWrapper.hide();
validationText.hide();
selectedFileWrapper.show();
filenameText.text(filenameText.data("text-template").replace("{filename}", selectedFilename));
}, 10);
var filename = data.files[0].name;
scope.data("upload-isactive", true);
scope.data("upload-start-time", Date.now());
var generateAssetUrl = scope.data("generate-asset-url");
preparingText.show();
scope.find(".file-upload-wrapper").hide();
scope.data("block-index", 0);
scope.data("block-ids", new Array());
(<any>scope[0]).doReset = function () {
fileUploadWrapper.show();
filenameInput.val("");
filenameText.text("");
selectedFileWrapper.hide();
validationText.hide();
};
$.ajax({
url: generateAssetUrl,
data: {
filename: filename,
__RequestVerificationToken: antiForgeryToken
},
type: "POST"
}).done(function (asset) {
data.url = asset.sasLocator;
data.multipart = false;
(<any>scope[0]).doUpload = function () {
var editedFilename = filenameInput.val() || selectedFilename;
if (!acceptFileTypesRegex.test(editedFilename)) {
validationText.show();
return;
}
scope.data("sas-locator", asset.sasLocator);
scope.find("input[name$='.FileName']").val(filename);
scope.find("input[name$='.WamsAssetId']").val(asset.assetId);
scope.data("upload-isactive", true);
scope.data("upload-start-time", Date.now());
var generateAssetUrl = scope.data("generate-asset-url");
scope.data("block-index", 0);
scope.data("block-ids", new Array());
preparingText.hide();
progressText.text(progressText.data("text-template").replace("{percentage}", 0)).show();
uploadingContainer.show();
preparingText.show();
selectedFileWrapper.hide();
validationText.hide();
var xhr = data.submit();
scope.data("xhr", xhr);
}).fail(function (xhr, status, error) {
preparingText.hide();
uploadingContainer.hide();
scope.data("upload-isactive", false);
scope.data("upload-start-time", null);
scope.find(".file-upload-wrapper").show();
alert("An error occurred. Error: " + error);
});
$.ajax({
url: generateAssetUrl,
data: {
filename: editedFilename,
__RequestVerificationToken: antiForgeryToken
},
type: "POST"
}).done(function (asset) {
data.url = asset.sasLocator;
data.multipart = false;
scope.data("sas-locator", asset.sasLocator);
scope.find("input[name$='.FileName']").val(editedFilename);
scope.find("input[name$='.WamsAssetId']").val(asset.assetId);
preparingText.hide();
progressText.text(progressText.data("text-template").replace("{percentage}", 0)).show();
uploadingContainer.show();
var xhr = data.submit();
scope.data("xhr", xhr);
}).fail(function (xhr, status, error) {
fileUploadWrapper.show();
selectedFileWrapper.show();
preparingText.hide();
uploadingContainer.hide();
scope.data("upload-isactive", false);
scope.data("upload-start-time", null);
alert("An error occurred. Error: " + error);
});
};
},
processfail: function (e, data) {
scope.find(".validation-text").show();
validationText.show();
filenameInput.val("");
filenameText.text("");
selectedFileWrapper.hide();
},
change: function (e, data) {
var prompt = fileInput.data("prompt");
@@ -269,7 +308,7 @@ module Orchard.Azure.MediaServices.CloudVideoEdit {
cancelLink.on("click", function (e) {
e.preventDefault();
if (confirm($(this).data("prompt"))) {
if (confirm($(this).data("cancel-prompt"))) {
var xhr = scope.data("xhr");
xhr.abort();
}
@@ -277,10 +316,24 @@ module Orchard.Azure.MediaServices.CloudVideoEdit {
}
export function initializeUploadDirect() {
var scope = $(".upload-direct").show();
scope.find(".reset-button").on("click", function (e) {
var doReset = (<any>$(this).closest(".async-upload")[0]).doReset;
if (!!doReset)
doReset();
});
scope.find(".upload-button").on("click", function (e) {
var doUpload = (<any>$(this).closest(".async-upload")[0]).doUpload;
if (!!doUpload)
doUpload();
});
requiredUploads = scope.find(".required-upload");
scope.find(".async-upload-input").each(function () {
scope.find(".async-upload-file-input").each(function () {
initializeUpload($(this));
});
@@ -293,10 +346,13 @@ module Orchard.Azure.MediaServices.CloudVideoEdit {
scope.data("is-submitting", true);
});
window.onbeforeunload = function (e) {
if ((hasActiveUploads() || hasCompletedUploads()) && !isSubmitting())
e.returnValue = scope.data("navigate-away-prompt");
};
$(window).on("beforeunload", function (e) {
if ((hasActiveUploads() || hasCompletedUploads()) && !isSubmitting()) {
var message = scope.data("navigate-away-prompt");
e.result = message;
return message;
}
});
}
}

View File

@@ -126,7 +126,7 @@ var Orchard;
}
});
scopeProxied.find(".async-upload-input").each(function () {
scopeProxied.find(".async-upload-file-input").each(function () {
initializeUpload($(this));
});

View File

@@ -123,7 +123,7 @@ module Orchard.Azure.MediaServices.CloudVideoEdit {
}
});
scopeProxied.find(".async-upload-input").each(function () {
scopeProxied.find(".async-upload-file-input").each(function () {
initializeUpload($(this));
});

View File

@@ -1,4 +1,4 @@
html {
html {
height: 100%;
}
body {
@@ -13,10 +13,13 @@ body {
}
.upload-direct .sync-upload-input,
.upload-proxied .sync-upload-input,
.upload-direct .async-upload-input,
.upload-proxied .async-upload-input {
.upload-direct .async-upload-file-input,
.upload-proxied .async-upload-file-input {
display: block;
margin-bottom: 4px;
}
.upload-direct .selected-file-wrapper,
.upload-proxied .selected-file-wrapper,
.upload-direct .progress-bar,
.upload-proxied .progress-bar,
.upload-direct .progress-text,
@@ -27,6 +30,10 @@ body {
.upload-proxied .cancel-upload {
display: none;
}
.upload-direct .selected-file-wrapper .filename-text,
.upload-proxied .selected-file-wrapper .filename-text {
color: #809f43;
}
.upload-direct .progress-bar,
.upload-proxied .progress-bar {
float: left;
@@ -88,3 +95,4 @@ body {
.status.uploaded {
color: #809f43;
}
/*# sourceMappingURL=cloudmedia-edit-cloudvideopart.css.map */

View File

@@ -15,14 +15,19 @@ body {
.upload-direct, .upload-proxied {
display: none;
.sync-upload-input, .async-upload-input {
.sync-upload-input, .async-upload-file-input {
display: block;
margin-bottom: 4px;
}
.progress-bar, .progress-text, .validation-text, .cancel-upload {
.selected-file-wrapper, .progress-bar, .progress-text, .validation-text, .cancel-upload {
display: none;
}
.selected-file-wrapper .filename-text {
color: @orchard-green;
}
.progress-bar {
float: left;
margin-top: 4px;

View File

@@ -13,7 +13,8 @@
var acceptFileTypes = extensions != null && extensions.Any() ? String.Format(@"(\.|\/)({0})$", String.Join("|", extensions)) : null;
var wamsAssetFieldName = String.Format("{0}.WamsAssetId", prefix);
<section class="async-upload" data-upload-accept-file-types="@acceptFileTypes"
<section class="async-upload"
data-upload-accept-file-types="@acceptFileTypes"
data-generate-asset-url="@Url.Action("GenerateWamsAsset", "Asset", new { area = "Orchard.Azure.MediaServices" })"
data-delete-asset-url="@Url.Action("DeleteWamsAsset", "Asset", new { area = "Orchard.Azure.MediaServices"})">
@@ -22,8 +23,16 @@
<input type="hidden" name="@String.Format("{0}.AssetId", prefix)" value="@wamsAssetViewModel.AssetId" />
@if (wamsAssetViewModel.WamsAssetId == null) {
<div class="file-upload-wrapper">
<input class="async-upload-input @if (isRequired) { <text> required-upload </text> }" name="@fileUploadName" type="file" @if (prompt != null) { <text> data-prompt="@prompt" </text> } />
<input class="async-upload-file-input @if (isRequired) { <text> required-upload </text> }" name="@fileUploadName" type="file" @if (prompt != null) { <text> data-prompt="@prompt" </text> } />
</div>
<div class="selected-file-wrapper">
<div class="filename-text" data-text-template="@T("Ready to upload file '{filename}'.")"></div>
<input class="filename-input text medium" type="text" name="@(fileUploadName + "Name")" placeholder="@T("Optional: Enter a different name for the uploaded file")" />
<button class="reset-button button grey" type="button">@T("Reset")</button>
<button class="upload-button button grey" type="button">@T("Upload")</button>
</div>
<div class="status preparing">@T("Preparing to upload...")</div>
@@ -32,7 +41,7 @@
<div class="progress"></div>
</div>
<span class="progress-text" data-text-template="@T("Uploading ({percentage}%)...")"></span>
<a class="cancel-link" href="#" data-prompt="@T("Are you sure you want to cancel this upload?")">@T("Cancel")</a><br />
<a class="cancel-link" href="#" data-cancel-prompt="@T("Are you sure you want to cancel this upload?")">@T("Cancel")</a><br />
<span class="progress-details hint" data-text-template="@T("Uploaded {uploaded} KB / {total} KB | Speed: {kbps} KB/s | Elapsed: {elapsed} | Remaining: {remaining}")"></span>
</div>
<div class="status uploaded" data-text-template="@T("Successfully uploaded file '{filename}'.")"></div>

View File

@@ -16,7 +16,7 @@
<input type="hidden" name="@String.Format("{0}.TemporaryFileName", prefix)" value="@tempFileViewModel.TemporaryFileName" />
<input type="hidden" name="@String.Format("{0}.FileSize", prefix)" value="@tempFileViewModel.FileSize" />
@if (String.IsNullOrWhiteSpace(tempFileViewModel.TemporaryFileName)) {
<input class="async-upload-input" name="@fileUploadName" type="file" />
<input class="async-upload-file-input" name="@fileUploadName" type="file" />
<div class="progress-bar">
<div class="progress"></div>
</div>

View File

@@ -2,7 +2,7 @@
<fieldset>
<legend>@T("Account credentials")</legend>
<p class="hint">@T("The account name and access key for your Microsoft Azure Media Services account can be obtained from the Windows Azure management portal at <a href='https://manage.windowsazure.com'>https://manage.windowsazure.com</a>.")</p>
<p class="hint">@T("The account name and access key for your Microsoft Azure Media Services account can be obtained from the Microsoft Azure management portal at <a href='https://manage.windowsazure.com'>https://manage.windowsazure.com</a>.")</p>
<p class="hint">@T("If you do not yet have a Microsoft Azure subscription, visit <a href='http://www.windowsazure.com/pricing/free-trial'>http://www.windowsazure.com/pricing/free-trial</a> to sign up for a free trial or buy a subscription.")</p>
<div>
<label>@T("Account name")</label>
@@ -18,7 +18,7 @@
<label>@T("Storage account access key")</label>
@Html.TextBoxFor(m => m.StorageAccountKey, new { @class = "text medium" })
@Html.ValidationMessageFor(m => m.StorageAccountKey)
<p class="hint">@T("Specify the account key for the underlying Microsoft Azure Storage account used by your Windows Azure Media Services instance if you want to automatically enable CORS support with the appropriate origin URLs for this web site. Enabling CORS support in your Windows Azure Storage account is required for uploading media files directly to Windows Azure Media Services. If you leave this field blank you will have to manually enable the appropriate CORS support for your Windows Azure Storage account using PowerShell.")</p>
<p class="hint">@T("Specify the account key for the underlying Microsoft Azure Storage account used by your Microsoft Azure Media Services instance if you want to automatically enable CORS support with the appropriate origin URLs for this web site. Enabling CORS support in your Microsoft Azure Storage account is required for uploading media files directly to Microsoft Azure Media Services. If you leave this field blank you will have to manually enable the appropriate CORS support for your Microsoft Azure Storage account using PowerShell.")</p>
</div>
<button id="test-button" type="submit" formaction="@Url.Action("TestCredentials")" class="button grey">@T("Test")</button>
</fieldset>