Skip to content

Commit

Permalink
issue #130 add upload file to card
Browse files Browse the repository at this point in the history
  • Loading branch information
cnam committed Nov 14, 2016
1 parent ec8229e commit d996ecd
Show file tree
Hide file tree
Showing 17 changed files with 256 additions and 122 deletions.
6 changes: 6 additions & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ module.exports = function (grunt) {
dest: 'web/assets/js/dropdownToggle.js',
filter: 'isFile'
},
{
flatten: true,
src: ['node_modules/angular-file-upload/dist/angular-file-upload.js'],
dest: 'web/assets/js/angular-file-upload.js',
filter: 'isFile'
},
{
flatten: true,
src: ['node_modules/angular-mm-foundation/src/position/position.js'],
Expand Down
13 changes: 8 additions & 5 deletions cmd/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,14 @@ func daemon(c *cobra.Command, a []string) {
m.Get("/starred", board.ListStarredBoards)
m.Post("/configure", binding.Json(models.BoardRequest{}), board.Configure)

m.Combo("/:board/connect").
Get(board.ListConnectBoard).
Post(binding.Json(models.BoardRequest{}), board.CreateConnectBoard).
Delete(board.DeleteConnectBoard)

m.Group("/:board", func() {
m.Combo("/connect").
Get(board.ListConnectBoard).
Post(binding.Json(models.BoardRequest{}), board.CreateConnectBoard).
Delete(board.DeleteConnectBoard)

m.Post("/upload", binding.MultipartForm(models.UploadForm{}), board.UploadFile)
})
}, middleware.Datasource())

m.Get("/board", middleware.Datasource(), board.ItemBoard)
Expand Down
10 changes: 7 additions & 3 deletions datasource/datasource.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package datasource

import (
"gitlab.com/leanlabsio/kanban/models"
)
import "gitlab.com/leanlabsio/kanban/models"

type DataSource interface {
CardSource
Expand All @@ -11,6 +9,7 @@ type DataSource interface {
UserSource
LabelSource
MilestoneSource
FileService
}

type CardSource interface {
Expand Down Expand Up @@ -51,3 +50,8 @@ type MilestoneSource interface {
ListMilestones(boardID string) ([]*models.Milestone, error)
CreateMilestone(*models.MilestoneRequest) (*models.Milestone, int, error)
}

// FileService represents uploaded file
type FileService interface {
UploadFile(boardID string, file models.UploadForm) (*models.File, error)
}
23 changes: 23 additions & 0 deletions datasource/gitlab/file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package gitlab

import (
"gitlab.com/leanlabsio/kanban/models"
"gitlab.com/leanlabsio/kanban/modules/gitlab"
)

// UploadFile uploads file to gitlab
func (ds GitLabDataSource) UploadFile(boardID string, file models.UploadForm) (*models.File, error) {
body, err := file.File.Open()
res, err := ds.client.UploadFile(boardID, file.File.Filename, body)

return newFileFromGitlab(res), err
}

// newFileFromGitlab creates new local file from gitlab file
func newFileFromGitlab(f *gitlab.File) *models.File {
return &models.File{
Alt: f.Alt,
URL: f.URL,
Markdown: f.Markdown,
}
}
15 changes: 15 additions & 0 deletions models/file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package models

import "mime/multipart"

// File represents uploaded file
type File struct {
Alt string `json:"alt"`
URL string `json:"url"`
Markdown string `json:"markdown"`
}

// UploadForm represents file uploaded
type UploadForm struct {
File *multipart.FileHeader `form:"file"`
}
47 changes: 47 additions & 0 deletions modules/gitlab/file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package gitlab

import (
"bytes"
"io"
"mime/multipart"
"net/http"
)

// File represents uploaded file to gitlab
//
// Gitlab API docs: http://docs.gitlab.com/ee/api/projects.html#upload-a-file
type File struct {
Alt string `json:"alt"`
URL string `json:"url"`
Markdown string `json:"markdown"`
}

// UploadFile uploads file to gitlab project
//
// Gitlab API docs: http://docs.gitlab.com/ee/api/projects.html#upload-a-file
func (g *GitlabContext) UploadFile(projectID, name string, file io.Reader) (*File, error) {
path := getUrl([]string{"projects", projectID, "uploads"})

body := new(bytes.Buffer)
writer := multipart.NewWriter(body)
part, err := writer.CreateFormFile("file", name)
if err != nil {
return nil, err
}
_, err = io.Copy(part, file)

err = writer.Close()
if err != nil {
return nil, err
}

req, _ := http.NewRequest("POST", path, body)
req.Header.Set("Content-Type", writer.FormDataContentType())

var ret File
if _, err := g.Do(req, &ret); err != nil {
return nil, err
}

return &ret, nil
}
4 changes: 2 additions & 2 deletions modules/gitlab/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ func (g *GitlabContext) StarredProjects(opt *ProjectListOptions) ([]*Project, *C
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#get-single-project
func (g *GitlabContext) ItemProject(project_id string) (*Project, error) {
path := getUrl([]string{"projects", strings.Replace(url.QueryEscape(project_id), ".", "%2E", -1)})
func (g *GitlabContext) ItemProject(projectID string) (*Project, error) {
path := getUrl([]string{"projects", strings.Replace(url.QueryEscape(projectID), ".", "%2E", -1)})
req, _ := http.NewRequest("GET", path, nil)

var ret Project
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"ng-sortable": "=1.3.6",
"sass-flex-mixin": "=1.0.3",
"lodash": "=4.13.1",
"twemoji": "=2.1.0"
"twemoji": "=2.1.0",
"angular-file-upload": "=2.3.4"
}
}
25 changes: 25 additions & 0 deletions routers/board/file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package board

import (
"net/http"

"gitlab.com/leanlabsio/kanban/models"
"gitlab.com/leanlabsio/kanban/modules/middleware"
)

// UploadFile uploads file to datasource provider
func UploadFile(ctx *middleware.Context, f models.UploadForm) {
res, err := ctx.DataSource.UploadFile(ctx.Params(":board"), f)

if err != nil {
ctx.JSON(http.StatusUnauthorized, &models.ResponseError{
Success: false,
Message: err.Error(),
})
return
}

ctx.JSON(http.StatusOK, &models.Response{
Data: res,
})
}
3 changes: 2 additions & 1 deletion src/board/board.module.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
'll.modal',
'mm.foundation.typeahead',
'720kb.datepicker',
'mm.foundation.tabs'
'mm.foundation.tabs',
'angularFileUpload'
]).config(['$stateProvider', '$urlMatcherFactoryProvider', function($stateProvider, $urlMatcherFactoryProvider) {
function valToString(val) {
return val != null ? val.toString() : val;
Expand Down
45 changes: 45 additions & 0 deletions src/board/components/md_editor.cmp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
(function(angular){
'use strict';

angular.module("gitlabKBApp").component("mdEditor",{
templateUrl: CLIENT_VERSION + "/assets/html/board/views/md-editor.html",
controller: 'MdEditorController',
bindings: {
description: '=',
rows: '='
}
}).controller('MdEditorController', [
'FileUploader',
'$state',
'AuthService',
'BoardService',
function(FileUploader,$state, AuthService, BoardService){
var ctrl = this;
ctrl.project_path = $state.params.project_path;
ctrl.progress = false;
ctrl.uploader = new FileUploader({
autoUpload: true
});

BoardService.get($state.params.project_path).then(function(board) {
ctrl.uploader.url = '/api/boards/' + board.project.id + '/upload';
});

ctrl.uploader.headers = {
'X-KB-Access-Token': AuthService.getCurrent()
};

ctrl.uploader.onProgressItem = function(item) {
ctrl.progress = true;
};

ctrl.uploader.onCompleteItem = function(item, response, status, headers) {
if (ctrl.description == undefined) {
ctrl.description = '';
}
ctrl.progress = false;
ctrl.description += '\n' + '\n' + response.data.markdown;
};
}
]);
}(window.angular));
1 change: 1 addition & 0 deletions src/board/controllers/card.create.ctrl.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
UserService.list(board.project.id).then(function(users) {
$scope.options = users;
});

$scope.board = board;

MilestoneService.list(board.project.id).then(function(milestones) {
Expand Down
27 changes: 1 addition & 26 deletions src/board/views/card/create.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,32 +22,7 @@ <h3>New issue</h3>
<small class="error" data-ng-show="issueForm.title.$invalid && !issueForm.title.$pristine">
This Field is required
</small>
<div class="mdeditor">
<div class="mdeditor-panel">
<a class="icon-edit"
data-ng-show="!isPreview"
data-ng-click="isPreview=true">
<i class="fa fa-eye"></i>
</a>
<a class="icon-edit"
data-ng-show="isPreview"
data-ng-click="isPreview=false">
<i class="fa fa-eye-slash"></i>
</a>&nbsp;
<a class="icon-edit" target="_blank" href="https://gitlab.com/help/markdown/markdown">
<i class="fa fa-question"></i>
</a>
</div>
<div class="preview" style="min-height: 228px;"
data-ng-show="isPreview"
data-ll-markdown
data-markdown="card.description"></div>
<textarea data-ng-show="! isPreview"
name="description"
placeholder="Description"
rows="10"
data-ng-model="card.description"></textarea>
</div>
<md-editor description="card.description" rows="10"></md-editor>
<button class="button right" type="submit" data-ng-disabled="issueForm.$invalid || isSaving">
Create
</button>
Expand Down
59 changes: 2 additions & 57 deletions src/board/views/card/view.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,32 +26,7 @@ <h3 class="subheader hide-for-medium-down" data-ng-show="! isEdit">
placeholder="Title"
required
data-ng-model="newCard.title">
<div class="mdeditor">
<div class="mdeditor-panel">
<a class="icon-edit"
data-ng-show="!isPreview"
data-ng-click="isPreview=true">
<i class="fa fa-eye"></i>
</a>
<a class="icon-edit"
data-ng-show="isPreview"
data-ng-click="isPreview=false">
<i class="fa fa-eye-slash"></i>
</a>&nbsp;
<a class="icon-edit" target="_blank" href="https://gitlab.com/help/markdown/markdown">
<i class="fa fa-question"></i>
</a>
</div>
<div class="preview" style="min-height: 228px;"
data-ng-show="isPreview"
data-ll-markdown
data-markdown="newCard.description"></div>
<textarea data-ng-show="! isPreview"
name="description"
placeholder="Description"
rows="10"
data-ng-model="newCard.description"></textarea>
</div>
<md-editor description="newCard.description" rows="10"></md-editor>
<button class="button small right" type="submit" data-ng-disabled="issueForm.$invalid || isSaving">Update</button>
</form>
<button class="button small left secondary" data-ng-click="isEdit=false;isPreview=false; discardCardDraft()">Cancel</button>
Expand Down Expand Up @@ -130,37 +105,7 @@ <h5 class="comment-header">{{comment.author.name}}
<form name="commentForm" data-ng-submit="submitComment();isPreviewComment=false;commentFormData.comment='';" class="comment-form">
<div class="row collapse prefix-round">
<div class="small-12 columns">
<div class="mdeditor">
<div class="mdeditor-panel">
<a class="icon-edit"
data-ng-show="!isPreviewComment"
data-ng-click="isPreviewComment=true">
<i class="fa fa-eye"></i>
</a>
<a class="icon-edit"
data-ng-show="isPreviewComment"
data-ng-click="isPreviewComment=false">
<i class="fa fa-eye-slash"></i>
</a>&nbsp;
<a class="icon-edit"
target="_blank"
href="https://gitlab.com/help/markdown/markdown">
<i class="fa fa-question"></i>
</a>
</div>
<div class="preview" style="min-height: 123px;"
data-ng-show="isPreviewComment"
data-ll-markdown
data-markdown="commentFormData.comment"></div>
<textarea data-ng-show="! isPreviewComment"
data-ng-focus="isCommentAdd"
data-ng-disabled="isSaving"
name="comment"
data-ng-model="commentFormData.comment"
placeholder="Leave a comment"
rows="5"
></textarea>
</div>
<md-editor description="commentFormData.comment" rows="5"></md-editor>
<button
class="button small right"
type="submit"
Expand Down
Loading

0 comments on commit d996ecd

Please sign in to comment.