mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-08 22:45:51 +01:00
Implementing file upload on the repository viewer
This commit is contained in:
@@ -31,6 +31,13 @@ class FileUploadController extends ScalatraServlet with FileUploadSupport with R
|
|||||||
}, FileUtil.isImage)
|
}, FileUtil.isImage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
post("/tmp"){
|
||||||
|
execute({ (file, fileId) =>
|
||||||
|
FileUtils.writeByteArrayToFile(new java.io.File(getTemporaryDir(session.getId), fileId), file.get)
|
||||||
|
session += Keys.Session.Upload(fileId) -> file.name
|
||||||
|
}, _ => true)
|
||||||
|
}
|
||||||
|
|
||||||
post("/file/:owner/:repository"){
|
post("/file/:owner/:repository"){
|
||||||
execute({ (file, fileId) =>
|
execute({ (file, fileId) =>
|
||||||
FileUtils.writeByteArrayToFile(new java.io.File(
|
FileUtils.writeByteArrayToFile(new java.io.File(
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package gitbucket.core.controller
|
package gitbucket.core.controller
|
||||||
|
|
||||||
import java.io.FileInputStream
|
import java.io.File
|
||||||
import javax.servlet.http.{HttpServletRequest, HttpServletResponse}
|
import javax.servlet.http.{HttpServletRequest, HttpServletResponse}
|
||||||
|
|
||||||
import gitbucket.core.plugin.PluginRegistry
|
import gitbucket.core.plugin.PluginRegistry
|
||||||
@@ -18,14 +18,12 @@ import gitbucket.core.service.WebHookService._
|
|||||||
import gitbucket.core.view
|
import gitbucket.core.view
|
||||||
import gitbucket.core.view.helpers
|
import gitbucket.core.view.helpers
|
||||||
import io.github.gitbucket.scalatra.forms._
|
import io.github.gitbucket.scalatra.forms._
|
||||||
import org.apache.commons.io.IOUtils
|
import org.apache.commons.io.FileUtils
|
||||||
import org.eclipse.jgit.api.{ArchiveCommand, Git}
|
import org.eclipse.jgit.api.{ArchiveCommand, Git}
|
||||||
import org.eclipse.jgit.archive.{TgzFormat, ZipFormat}
|
import org.eclipse.jgit.archive.{TgzFormat, ZipFormat}
|
||||||
import org.eclipse.jgit.dircache.{DirCache, DirCacheBuilder}
|
import org.eclipse.jgit.dircache.{DirCache, DirCacheBuilder}
|
||||||
import org.eclipse.jgit.errors.MissingObjectException
|
import org.eclipse.jgit.errors.MissingObjectException
|
||||||
import org.eclipse.jgit.lib._
|
import org.eclipse.jgit.lib._
|
||||||
import org.eclipse.jgit.revwalk.RevCommit
|
|
||||||
import org.eclipse.jgit.treewalk._
|
|
||||||
import org.scalatra._
|
import org.scalatra._
|
||||||
|
|
||||||
|
|
||||||
@@ -45,6 +43,13 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
|||||||
ArchiveCommand.registerFormat("zip", new ZipFormat)
|
ArchiveCommand.registerFormat("zip", new ZipFormat)
|
||||||
ArchiveCommand.registerFormat("tar.gz", new TgzFormat)
|
ArchiveCommand.registerFormat("tar.gz", new TgzFormat)
|
||||||
|
|
||||||
|
case class UploadForm(
|
||||||
|
branch: String,
|
||||||
|
path: String,
|
||||||
|
uploadFiles: String,
|
||||||
|
message: Option[String]
|
||||||
|
)
|
||||||
|
|
||||||
case class EditorForm(
|
case class EditorForm(
|
||||||
branch: String,
|
branch: String,
|
||||||
path: String,
|
path: String,
|
||||||
@@ -71,6 +76,13 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
|||||||
issueId: Option[Int]
|
issueId: Option[Int]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val uploadForm = mapping(
|
||||||
|
"branch" -> trim(label("Branch", text(required))),
|
||||||
|
"path" -> trim(label("Path", text())),
|
||||||
|
"uploadFiles" -> trim(label("Upload files", text(required))),
|
||||||
|
"message" -> trim(label("Message", optional(text()))),
|
||||||
|
)(UploadForm.apply)
|
||||||
|
|
||||||
val editorForm = mapping(
|
val editorForm = mapping(
|
||||||
"branch" -> trim(label("Branch", text(required))),
|
"branch" -> trim(label("Branch", text(required))),
|
||||||
"path" -> trim(label("Path", text())),
|
"path" -> trim(label("Path", text())),
|
||||||
@@ -173,10 +185,37 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
|||||||
val (branch, path) = repository.splitPath(multiParams("splat").head)
|
val (branch, path) = repository.splitPath(multiParams("splat").head)
|
||||||
val protectedBranch = getProtectedBranchInfo(repository.owner, repository.name, branch).needStatusCheck(context.loginAccount.get.userName)
|
val protectedBranch = getProtectedBranchInfo(repository.owner, repository.name, branch).needStatusCheck(context.loginAccount.get.userName)
|
||||||
html.editor(branch, repository, if(path.length == 0) Nil else path.split("/").toList,
|
html.editor(branch, repository, if(path.length == 0) Nil else path.split("/").toList,
|
||||||
None, JGitUtil.ContentInfo("text", None, None, Some("UTF-8")),
|
None, JGitUtil.ContentInfo("text", None, None, Some("UTF-8")), protectedBranch)
|
||||||
protectedBranch)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
get("/:owner/:repository/upload/*")(writableUsersOnly { repository =>
|
||||||
|
val (branch, path) = repository.splitPath(multiParams("splat").head)
|
||||||
|
val protectedBranch = getProtectedBranchInfo(repository.owner, repository.name, branch).needStatusCheck(context.loginAccount.get.userName)
|
||||||
|
html.upload(branch, repository, if(path.length == 0) Nil else path.split("/").toList, protectedBranch)
|
||||||
|
})
|
||||||
|
|
||||||
|
post("/:owner/:repository/upload", uploadForm)(writableUsersOnly { (form, repository) =>
|
||||||
|
val files = form.uploadFiles.split("\n").map { line =>
|
||||||
|
val i = line.indexOf(":")
|
||||||
|
CommitFile(line.substring(0, i).trim, line.substring(i + 1).trim)
|
||||||
|
}
|
||||||
|
|
||||||
|
commitFiles(
|
||||||
|
repository = repository,
|
||||||
|
branch = form.branch,
|
||||||
|
path = form.path,
|
||||||
|
files = files,
|
||||||
|
message = form.message.getOrElse(s"Add files via upload")
|
||||||
|
)
|
||||||
|
|
||||||
|
if(form.path.length == 0){
|
||||||
|
redirect(s"/${repository.owner}/${repository.name}/tree/${form.branch}")
|
||||||
|
} else {
|
||||||
|
redirect(s"/${repository.owner}/${repository.name}/tree/${form.branch}/${form.path}")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
get("/:owner/:repository/edit/*")(writableUsersOnly { repository =>
|
get("/:owner/:repository/edit/*")(writableUsersOnly { repository =>
|
||||||
val (branch, path) = repository.splitPath(multiParams("splat").head)
|
val (branch, path) = repository.splitPath(multiParams("splat").head)
|
||||||
val protectedBranch = getProtectedBranchInfo(repository.owner, repository.name, branch).needStatusCheck(context.loginAccount.get.userName)
|
val protectedBranch = getProtectedBranchInfo(repository.owner, repository.name, branch).needStatusCheck(context.loginAccount.get.userName)
|
||||||
@@ -547,65 +586,30 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
|
||||||
* Upload file to a branch.
|
|
||||||
*/
|
|
||||||
post("/:owner/:repository/files/upload")(writableUsersOnly { repository =>
|
|
||||||
defining(repository.owner, repository.name){ case (owner, name) =>
|
|
||||||
(for {
|
|
||||||
data <- extractFromJsonBody[UploadFiles] if data.isValid
|
|
||||||
} yield {
|
|
||||||
Directory.getAttachedDir(owner, name) match {
|
|
||||||
case dir if (dir.exists && dir.isDirectory) =>
|
|
||||||
val _commitFiles = data.fileIds.map { case (fileName, id) =>
|
|
||||||
dir.listFiles.find(_.getName.startsWith(id + ".")).map { file =>
|
|
||||||
CommitFile(id, fileName, using(new FileInputStream(file))(IOUtils.toByteArray))
|
|
||||||
}
|
|
||||||
}.toList
|
|
||||||
|
|
||||||
val finalCommitFiles = _commitFiles.flatten
|
|
||||||
if(finalCommitFiles.size == data.fileIds.size) {
|
|
||||||
commitFiles(
|
|
||||||
repository,
|
|
||||||
files = finalCommitFiles,
|
|
||||||
branch = data.branch,
|
|
||||||
path = data.path,
|
|
||||||
message = data.message)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
org.scalatra.NotAcceptable(
|
|
||||||
s"""{"message":
|
|
||||||
|"$repository doesn't contain all the files you specified in the body"}""".stripMargin)
|
|
||||||
}
|
|
||||||
|
|
||||||
case _ => org.scalatra.NotFound(s"""{"message": "$repository doesn't contain any attached files"}""")
|
|
||||||
}
|
|
||||||
|
|
||||||
}) getOrElse
|
|
||||||
org.scalatra.NotAcceptable("""{"message": "FileIds can't be an empty list"}""")
|
|
||||||
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
case class UploadFiles(branch: String, path: String, fileIds : Map[String,String], message: String) {
|
case class UploadFiles(branch: String, path: String, fileIds : Map[String,String], message: String) {
|
||||||
lazy val isValid: Boolean = fileIds.size > 0
|
lazy val isValid: Boolean = fileIds.size > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
case class CommitFile(fileId: String, name: String, fileBytes: Array[Byte])
|
case class CommitFile(id: String, name: String)
|
||||||
|
|
||||||
private def commitFiles(repository: RepositoryService.RepositoryInfo,
|
private def commitFiles(repository: RepositoryService.RepositoryInfo,
|
||||||
files: List[CommitFile],
|
files: Seq[CommitFile],
|
||||||
branch: String, path: String, message: String) = {
|
branch: String, path: String, message: String) = {
|
||||||
|
// prepend path to the filename
|
||||||
_commitFile(repository, branch, path, message) { case (git, headTip, builder, inserter) =>
|
val newFiles = files.map { file =>
|
||||||
JGitUtil.processTree(git, headTip) { (path, tree) =>
|
file.copy(name = if(path.length == 0) file.name else s"${path}/${file.name}")
|
||||||
builder.add(JGitUtil.createDirCacheEntry(path, tree.getEntryFileMode, tree.getEntryObjectId))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
files.foreach { item =>
|
_commitFile(repository, branch, message) { case (git, headTip, builder, inserter) =>
|
||||||
val fileName = item.name
|
JGitUtil.processTree(git, headTip) { (path, tree) =>
|
||||||
val bytes = item.fileBytes
|
if(!newFiles.exists(_.name.contains(path))) {
|
||||||
builder.add(JGitUtil.createDirCacheEntry(fileName,
|
builder.add(JGitUtil.createDirCacheEntry(path, tree.getEntryFileMode, tree.getEntryObjectId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newFiles.foreach { file =>
|
||||||
|
val bytes = FileUtils.readFileToByteArray(new File(getTemporaryDir(session.getId), file.id))
|
||||||
|
builder.add(JGitUtil.createDirCacheEntry(file.name,
|
||||||
FileMode.REGULAR_FILE, inserter.insert(Constants.OBJ_BLOB, bytes)))
|
FileMode.REGULAR_FILE, inserter.insert(Constants.OBJ_BLOB, bytes)))
|
||||||
builder.finish()
|
builder.finish()
|
||||||
}
|
}
|
||||||
@@ -619,7 +623,7 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
|||||||
val newPath = newFileName.map { newFileName => if(path.length == 0) newFileName else s"${path}/${newFileName}" }
|
val newPath = newFileName.map { newFileName => if(path.length == 0) newFileName else s"${path}/${newFileName}" }
|
||||||
val oldPath = oldFileName.map { oldFileName => if(path.length == 0) oldFileName else s"${path}/${oldFileName}" }
|
val oldPath = oldFileName.map { oldFileName => if(path.length == 0) oldFileName else s"${path}/${oldFileName}" }
|
||||||
|
|
||||||
_commitFile(repository, branch, path, message){ case (git, headTip, builder, inserter) =>
|
_commitFile(repository, branch, message){ case (git, headTip, builder, inserter) =>
|
||||||
val permission = JGitUtil.processTree(git, headTip){ (path, tree) =>
|
val permission = JGitUtil.processTree(git, headTip){ (path, tree) =>
|
||||||
// Add all entries except the editing file
|
// Add all entries except the editing file
|
||||||
if(!newPath.contains(path) && !oldPath.contains(path)){
|
if(!newPath.contains(path) && !oldPath.contains(path)){
|
||||||
@@ -639,7 +643,7 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private def _commitFile(repository: RepositoryService.RepositoryInfo,
|
private def _commitFile(repository: RepositoryService.RepositoryInfo,
|
||||||
branch: String, path: String, message: String)(f: (Git, ObjectId, DirCacheBuilder, ObjectInserter) => Unit) = {
|
branch: String, message: String)(f: (Git, ObjectId, DirCacheBuilder, ObjectInserter) => Unit) = {
|
||||||
|
|
||||||
LockUtil.lock(s"${repository.owner}/${repository.name}") {
|
LockUtil.lock(s"${repository.owner}/${repository.name}") {
|
||||||
using(Git.open(getRepositoryDir(repository.owner, repository.name))) { git =>
|
using(Git.open(getRepositoryDir(repository.owner, repository.name))) { git =>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
s"${(repository.name :: pathList).mkString("/")} at ${helpers.encodeRefName(branch)} - ${repository.owner}/${repository.name}"
|
s"${(repository.name :: pathList).mkString("/")} at ${helpers.encodeRefName(branch)} - ${repository.owner}/${repository.name}"
|
||||||
}, Some(repository)) {
|
}, Some(repository)) {
|
||||||
@gitbucket.core.html.menu("files", repository, Some(branch), info, error){
|
@gitbucket.core.html.menu("files", repository, Some(branch), info, error){
|
||||||
<div class="head">
|
<div class="head" style="height: 24px;">
|
||||||
<div class="pull-right">
|
<div class="pull-right">
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
<a href="@helpers.url(repository)/find/@helpers.encodeRefName(branch)" class="btn btn-sm btn-default" data-hotkey="t"><i class="octicon octicon-search"></i></a>
|
<a href="@helpers.url(repository)/find/@helpers.encodeRefName(branch)" class="btn btn-sm btn-default" data-hotkey="t"><i class="octicon octicon-search"></i></a>
|
||||||
@@ -67,27 +67,24 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
<div class="pull-left">
|
||||||
@gitbucket.core.helper.html.branchcontrol(branch, repository, hasWritePermission){
|
@gitbucket.core.helper.html.branchcontrol(branch, repository, hasWritePermission){
|
||||||
@repository.branchList.map { x =>
|
@repository.branchList.map { x =>
|
||||||
<li><a href="@helpers.url(repository)/tree/@helpers.encodeRefName(x)">@gitbucket.core.helper.html.checkicon(x == branch) @x</a></li>
|
<li><a href="@helpers.url(repository)/tree/@helpers.encodeRefName(x)">@gitbucket.core.helper.html.checkicon(x == branch) @x</a></li>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@if(pathList.isEmpty){
|
@if(pathList.nonEmpty){
|
||||||
@*
|
|
||||||
@branchPullRequest.map{ case (pullRequest, issue) =>
|
|
||||||
<a href="@url(repository)/pull/@pullRequest.issueId" class="btn btn-sm btn-pullrequest-branch" title="@issue.title" data-toggle="tooltip">View #@pullRequest.issueId</a>
|
|
||||||
}.getOrElse {
|
|
||||||
<a href="@url(repository)/compare?head=@urlEncode(encodeRefName(branch))" class="btn btn-sm btn-success" @if(loginAccount.isEmpty){disabled}>New pull request</a>
|
|
||||||
}
|
|
||||||
*@
|
|
||||||
} else {
|
|
||||||
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName(branch)">@repository.name</a> /
|
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName(branch)">@repository.name</a> /
|
||||||
@pathList.zipWithIndex.map { case (section, i) =>
|
@pathList.zipWithIndex.map { case (section, i) =>
|
||||||
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName(branch)/@pathList.take(i + 1).mkString("/")">@section</a> /
|
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName(branch)/@pathList.take(i + 1).mkString("/")">@section</a> /
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
</div>
|
||||||
@if(hasWritePermission){
|
@if(hasWritePermission){
|
||||||
<a href="@helpers.url(repository)/new/@helpers.encodeRefName(branch)/@pathList.mkString("/")" class="btn btn-sm btn-default pc" title="Create a new file here"><i class="octicon octicon-plus"></i></a>
|
<div class="btn-group pull-left" style="margin-left: 4px;">
|
||||||
|
<a href="@helpers.url(repository)/new/@helpers.encodeRefName(branch)/@pathList.mkString("/")" class="btn btn-sm btn-default pc" title="Create a new file"><i class="octicon octicon-plus"></i></a>
|
||||||
|
<a href="@helpers.url(repository)/upload/@helpers.encodeRefName(branch)/@pathList.mkString("/")" class="btn btn-sm btn-default pc" title="Upload files"><i class="octicon octicon-cloud-upload"></i></a>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<table class="table table-hover">
|
<table class="table table-hover">
|
||||||
|
|||||||
103
src/main/twirl/gitbucket/core/repo/upload.scala.html
Normal file
103
src/main/twirl/gitbucket/core/repo/upload.scala.html
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
@(branch: String,
|
||||||
|
repository: gitbucket.core.service.RepositoryService.RepositoryInfo,
|
||||||
|
pathList: List[String],
|
||||||
|
protectedBranch: Boolean)(implicit context: gitbucket.core.controller.Context)
|
||||||
|
@import gitbucket.core.view.helpers
|
||||||
|
@import gitbucket.core.util.FileUtil
|
||||||
|
@gitbucket.core.html.main(s"Upload Files at ${branch} - ${repository.owner}/${repository.name}", Some(repository)) {
|
||||||
|
@gitbucket.core.html.menu("files", repository){
|
||||||
|
@if(protectedBranch){
|
||||||
|
<div class="alert alert-danger">branch @branch is protected.</div>
|
||||||
|
}
|
||||||
|
<form method="POST" action="@helpers.url(repository)/upload" id="upload-form">
|
||||||
|
@*
|
||||||
|
<span class="error" id="error-newFileName"></span>
|
||||||
|
*@
|
||||||
|
<div class="head">
|
||||||
|
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName(branch)">@repository.name</a> /
|
||||||
|
@pathList.zipWithIndex.map { case (section, i) =>
|
||||||
|
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName(branch)/@pathList.take(i + 1).mkString("/")">@section</a> /
|
||||||
|
}
|
||||||
|
<input type="hidden" name="branch" id="branch" value="@branch"/>
|
||||||
|
<input type="hidden" name="path" id="path" value="@pathList.mkString("/")"/>
|
||||||
|
</div>
|
||||||
|
<table class="table table-bordered">
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 0px; background-color: #f4f4f4; border: 1px #ddd solid;">
|
||||||
|
<div id="upload-area" style="text-align: center; padding-top: 20px; padding-bottom: 20px; font-size: 120%;">
|
||||||
|
Drag files here to add them to your repository
|
||||||
|
</div>
|
||||||
|
<ul id="upload-files">
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<div class="panel panel-default issue-comment-box">
|
||||||
|
<div class="panel-body">
|
||||||
|
<div>
|
||||||
|
<strong>Commit changes</strong>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" name="message" class="form-control"/>
|
||||||
|
</div>
|
||||||
|
<div style="text-align: right;">
|
||||||
|
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName(branch)/@{pathList.mkString("/")}" class="btn btn-danger">Cancel</a>
|
||||||
|
<input type="submit" id="commit" class="btn btn-success" value="Commit changes" disabled="true"/>
|
||||||
|
<input type="hidden" id="upload-files-data" name="uploadFiles" value=""/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
<style type="text/css">
|
||||||
|
ul#upload-files {
|
||||||
|
list-style: none;
|
||||||
|
padding-left: 0px;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
li.upload-file {
|
||||||
|
border-top: 1px #f4f4f4 solid;
|
||||||
|
background-color: white;
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
$(function(){
|
||||||
|
$('#upload-area').dropzone({
|
||||||
|
url: '@context.path/upload/tmp',
|
||||||
|
maxFilesize: 10,
|
||||||
|
clickable: true,
|
||||||
|
previewTemplate: "<div class=\"dz-preview\">\n <div class=\"dz-progress\"><span class=\"dz-upload\" data-dz-uploadprogress>Uploading your files...</span></div>\n <div class=\"dz-error-message\"><span data-dz-errormessage></span></div>\n</div>",
|
||||||
|
success: function(file, id) {
|
||||||
|
file.previewElement.remove();
|
||||||
|
$('#upload-files').append($('<li class="upload-file">')
|
||||||
|
.append($('<span>').data('id', id).text(file.name))
|
||||||
|
.append($('<a class="delete" href="javascript:void(0);" style="margin-left: 4px;">(delete)</a>')));
|
||||||
|
updateCommitButtonStatus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#upload-form').submit(function(){
|
||||||
|
try {
|
||||||
|
var data = '';
|
||||||
|
$.each($('li.upload-file span'), function(i, e){
|
||||||
|
data = data + $(e).data('id') + ':' + $(e).text() + '\n';
|
||||||
|
});
|
||||||
|
$('#upload-files-data').val(data);
|
||||||
|
} catch(e){
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('click', 'a.delete', function(e){
|
||||||
|
$(e.target).parent().remove();
|
||||||
|
updateCommitButtonStatus();
|
||||||
|
});
|
||||||
|
|
||||||
|
function updateCommitButtonStatus(){
|
||||||
|
$('#commit').attr('disabled', $('.upload-file').length == 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@@ -38,9 +38,7 @@ h6 {
|
|||||||
|
|
||||||
.octicon,.mega-octicon{
|
.octicon,.mega-octicon{
|
||||||
color : #999;
|
color : #999;
|
||||||
width: 14px;
|
font-size: 14px;
|
||||||
height: 14px;
|
|
||||||
/*font-size: 14px;*/
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user