WIP - Close to done with add/edit board modal

This commit is contained in:
kiswa 2016-08-16 22:02:25 +00:00
parent af2186a1ca
commit f0ba3956d4
14 changed files with 390 additions and 48 deletions

View File

@ -20,6 +20,7 @@ let gulp = require('gulp'),
scssLint = require('gulp-scss-lint'),
sass = require('gulp-sass'),
cssImport = require('gulp-cssimport'),
cssPrefixer = require('gulp-autoprefixer'),
cssMinify = require('gulp-cssnano'),
@ -84,6 +85,7 @@ gulp.task('scss', () => {
]
}))
.pipe(concat('styles.css'))
.pipe(cssImport({}))
.pipe(cssPrefixer())
.pipe(gulp.dest('dist/css/'));
});
@ -127,8 +129,11 @@ gulp.task('system-build', ['tsc'], () => {
});
gulp.task('minify', () => {
// jsMinify options object is temporary due to problem in Angular RC5
let js = gulp.src('dist/js/**/*.js')
.pipe(jsMinify())
.pipe(jsMinify({
mangle: { screw_ie8 : true, keep_fnames: true }
}))
.pipe(gulp.dest('dist/js/'));
let css = gulp.src('dist/css/styles.css')

View File

@ -42,12 +42,14 @@
"chartist-plugin-tooltip": "git+https://github.com/Globegitter/chartist-plugin-tooltip.git",
"core-js": "^2.4.1",
"del": "^2.2.1",
"dragula": "^3.7.1",
"gulp": "^3.9.1",
"gulp-autoprefixer": "^3.1.0",
"gulp-chmod": "^1.3.0",
"gulp-composer": "^0.4.0",
"gulp-concat": "^2.6.0",
"gulp-coverage": "^0.3.38",
"gulp-cssimport": "^3.1.0",
"gulp-cssnano": "^2.1.2",
"gulp-imagemin": "^3.0.2",
"gulp-mocha": "^3.0.0",
@ -58,6 +60,7 @@
"gulp-uglify": "^2.0.0",
"gulp-util": "^3.0.7",
"merge-stream": "^1.0.0",
"ng2-dragula": "^1.1.10",
"reflect-metadata": "^0.1.8",
"rxjs": "5.0.0-beta.6",
"scss-base": "^1.1.6",

View File

@ -0,0 +1,78 @@
export class BoardData {
constructor(public title = '',
public boardName = '',
public columns = [],
public categories = [],
public issueTrackers = [],
public users = [],
public categoryDefaultColor = '#ffffe0',
public newColumnName = '',
public newCategoryName = '',
public issueTrackerUrl = '',
public issueTrackerBugId = '') { }
addColumn(): void {
if (this.newColumnName === '') {
return;
}
this.columns.push({ name: this.newColumnName });
this.newColumnName = '';
}
removeColumn(column): void {
let index = this.columns.indexOf(column);
if (index === -1) {
return;
}
this.columns.splice(index, 1);
}
addCategory(): void {
if (this.newCategoryName === '') {
return;
}
this.categories.push({
name: this.newCategoryName,
defaultColor: this.categoryDefaultColor
});
this.newCategoryName = '';
}
removeCategory(category): void {
let index = this.categories.indexOf(category);
if (index === -1) {
return;
}
this.categories.splice(index, 1);
}
addIssueTracker(): void {
if (this.issueTrackerUrl === '' || this.issueTrackerBugId === '') {
return;
}
this.issueTrackers.push({
url: this.issueTrackerUrl,
bugId: this.issueTrackerBugId
});
this.issueTrackerUrl = '';
this.issueTrackerBugId = '';
}
removeIssueTracker(tracker): void {
let index = this.issueTrackers.indexOf(tracker);
if (index === -1) {
return;
}
this.issueTrackers.splice(index, 1);
}
}

View File

@ -63,8 +63,8 @@
</ul>
</td>
<td>
<a href=""><i class="icon icon-edit"></i></a>
<a href=""><i class="icon icon-trash-empty"></i></a>
<a href="" title="Edit Board"><i class="icon icon-edit color-primary"></i></a>
<a href="" title="Remove Board"><i class="icon icon-trash-empty color-secondary"></i></a>
<label><input type="checkbox" checked> Active</label>
</td>
</tr>
@ -82,8 +82,8 @@
</ul>
</td>
<td>
<a href=""><i class="icon icon-edit"></i></a>
<a href=""><i class="icon icon-trash-empty"></i></a>
<a href="" title="Edit Board"><i class="icon icon-edit color-primary"></i></a>
<a href="" title="Remove Board"><i class="icon icon-trash-empty color-secondary"></i></a>
<label><input type="checkbox" checked> Active</label>
</td>
</tr>
@ -104,27 +104,118 @@
<input type="text" name="board-name" placeholder="Board Name"
[(ngModel)]="modalProps.boardName">
</label>
<div class="half-modal">
<label>Columns</label>
<p>TODO: Display existing columns</p>
<ul class="modal-list" [hidden]="!modalProps.columns.length"
[dragula]="'columns-bag'" [dragulaModel]="modalProps.columns">
<li *ngFor="let column of modalProps.columns">
<i class="icon icon-resize-vertical"></i>
{{ column.name }}
<span class="actions">
<i class="icon icon-edit color-primary"></i>
<i class="icon icon-trash-empty color-secondary"
(click)="modalProps.removeColumn(column)"></i>
</span>
</li>
</ul>
<div class="quick-add">
<input type="text" name="new-column"
placeholder="Column Name" [(ngModel)]="modalProps.newColumnName">
<button class="flat" (click)="addColumn()">
<i class="icon icon-plus"></i>
</button>
<form>
<input type="text" name="new-column"
placeholder="Column Name"
[(ngModel)]="modalProps.newColumnName">
<button type="submit" class="flat" title="Add Column"
(click)="modalProps.addColumn()">
<i class="icon icon-plus"></i>
</button>
</form>
</div>
</div>
<div class="half-modal">
<label>Categories</label>
<p>TODO: List existing categories</p>
<div class="quick-add">
<input type="text" name="new-category" placeholder="Category Name"
[(ngModel)]="modalProps.newCategoryName">
<button class="flat" (click)="addCategory()">
<i class="icon icon-plus"></i>
</button>
<ul *ngIf="modalProps.categories.length" class="modal-list">
<li *ngFor="let category of modalProps.categories">
{{ category.name }}
<span class="actions">
<span class="badge" title="Default Task Color"
[style.background-color]="getColor(category)"></span>
<i class="icon icon-edit color-primary"></i>
<i class="icon icon-trash-empty color-secondary"
(click)="modalProps.removeCategory(category)"></i>
</span>
</li>
</ul>
<div class="quick-add categories">
<form>
<input type="text" name="new-category"
placeholder="Category Name"
[(ngModel)]="modalProps.newCategoryName">
<input type="color" name="category-default-color"
title="Default Task Color"
[(ngModel)]="modalProps.categoryDefaultColor">
<button type="submit" class="flat" title="Add Category"
(click)="modalProps.addCategory()">
<i class="icon icon-plus"></i>
</button>
</form>
</div>
</div>
<div class="clearfix"></div>
<div class="issue-trackers">
<label>
Issue Trackers
<i class="icon icon-help-circled"
alt="Example URL: https://github.com/kiswa/TaskBoard/issues/%BUGID\1%
Example RegExp: (?:Issue)?#(\d+)"></i>
</label>
<ul *ngIf="modalProps.issueTrackers.length" class="modal-list">
<li *ngFor="let tracker of modalProps.issueTrackers">
{{ tracker.url }} | {{ tracker.bugId }}
<span class="actions">
<i class="icon icon-edit color-primary"></i>
<i class="icon icon-trash-empty color-secondary"
(click)="modalProps.removeIssueTracker(tracker)"></i>
</span>
</li>
</ul>
<div>
<form>
<input type="text" name="issue-tracker"
placeholder="Issue Tracker URL - use %BUGID% as placeholder"
[(ngModel)]="modalProps.issueTrackerUrl">
<input type="text" name="issue-tracker-bug-id"
placeholder="BUGID RegExp"
[(ngModel)]="modalProps.issueTrackerBugId">
<button type="submit" class="flat" title="Add Issue Tracker"
(click)="modalProps.addIssueTracker()">
<i class="icon icon-plus"></i>
</button>
</form>
</div>
</div>
<div class="users">
<label>Select Users</label>
<br><strong>TODO: List users with checkboxes</strong>
<p>
<strong>*</strong> Including a Board Admin, makes
them an admin of this board.<br>
<em>Administrators have access to all boards and are
not listed here.</em>
</p>
</div>
<div class="buttons">
<button (click)="addBoard()">
<i class="icon icon-plus"></i>
Add Board
</button>
<button class="flat" (click)="modal.close(MODAL_ID)">
Cancel
</button>
</div>
</tb-modal>

View File

@ -1,5 +1,7 @@
import { Component } from '@angular/core';
import { Dragula, DragulaService } from 'ng2-dragula/ng2-dragula';
import {
ApiResponse,
User,
@ -9,24 +11,26 @@ import {
NotificationsService,
AuthService
} from '../../shared/index';
import { BoardData } from './board-data.model';
@Component({
selector: 'tb-board-settings',
templateUrl: 'app/settings/board-settings/board-settings.component.html',
directives: [ Modal ]
directives: [ Modal, Dragula ],
viewProviders: [ DragulaService ]
})
export class BoardSettings {
private activeUser: User;
private loading = true;
private modalProps;
private modalProps: BoardData;
private MODAL_ID: string;
constructor(private auth: AuthService, private modal: ModalService) {
constructor(private auth: AuthService, private modal: ModalService,
private dragula: DragulaService) {
this.MODAL_ID = 'board-addedit-form';
this.modalProps = {
boardName: ''
};
this.modalProps = new BoardData();
auth.userChanged
.subscribe(activeUser => {
@ -34,11 +38,30 @@ export class BoardSettings {
});
}
ngAfterContentInit() {
let ul = document.getElementsByClassName('modal-list')[0];
this.dragula.setOptions('columns-bag', {
moves: (el, container, handle) => {
return handle.classList.contains('icon-resize-vertical');
},
mirrorContainer: ul
});
}
private getColor(category: any): string {
return category.defaultColor;
}
private showModal(title: string): void {
let isAdd = (title === 'Add');
this.modalProps = {
title: title
};
if (isAdd) {
this.modalProps = new BoardData(title);
} else {
// TODO: Load board data in constructor
this.modalProps = new BoardData(title);
}
this.modal.open(this.MODAL_ID);
}

View File

@ -29,13 +29,21 @@
<td>Example Board</td>
<td>Item assigned to user: admin</td>
<td>Set item color: #debee8</td>
<td><a href="#"><i class="icon icon-trash-empty"></i></a></td>
<td>
<a href="#" title="Remove Automatic Action">
<i class="icon icon-trash-empty color-secondary"></i>
</a>
</td>
</tr>
<tr>
<td>Example Board</td>
<td>Item moved to column: Col3</td>
<td>Set item color: #debee8</td>
<td><a href="#"><i class="icon icon-trash-empty"></i></a></td>
<td>
<a href="#" title="Remove Automatic Action">
<i class="icon icon-trash-empty color-secondary"></i>
</a>
</td>
</tr>
</tbody>
</table>
@ -86,7 +94,10 @@
</tbody>
</table>
<button class="right">Add Action</button>
<button class="right" disabled>
<i class="icon icon-plus"></i>
Add Action
</button>
</div>
</section>
</div>

View File

@ -79,7 +79,7 @@
<label>
Default Board
<i *ngIf="modalProps.title === 'Add'"
title="Selecting a default board adds the user to that board."
alt="Selecting a default board adds the user to that board."
class="icon icon-help-circled"></i>
<select>
<option>TODO</option>

View File

@ -1,4 +1,4 @@
<div *ngIf="isOpen">
<div [hidden]="!isOpen">
<div class="modal-overlay" (click)="close(true)"></div>
<div class="modal" [ngClass]="{ wide: wide }">

View File

@ -114,8 +114,8 @@
.badge {
font-size: .5em;
margin-right: -3px;
margin-top: 3px;
margin-right: -2px;
margin-top: 2px;
}
}

View File

@ -90,6 +90,25 @@ button {
width: 20px;
}
.icon-help-circled {
position: relative;
&:hover:after {
@include shadow-high;
background-color: $white;
border: 1px solid $color-border;
content: attr(alt);
left: 20px;
min-width: 250px;
padding: 7px;
position: absolute;
text-align: left;
top: -1em;
z-index: 100;
}
}
.color-primary {
color: $color-primary;
}
@ -107,6 +126,10 @@ button {
font-size: .8em;
}
.clearfix {
@include clearfix;
}
.row {
@include row();
@ -130,6 +153,7 @@ button {
}
.badge {
border: 1px solid $color-border;
background-color: $color-tertiary;
border-radius: 33%;
box-shadow: inset 1px 1px rgba(0, 0, 0, .1);

View File

@ -3,14 +3,11 @@
margin: 7px 1em;
.activity-log {
margin: 7px;
margin-right: 0;
.quick-add {
padding: 0;
button {
float: right;
font-size: .9em;
padding: 3px 5px;
vertical-align: top;
}
}
@ -20,12 +17,17 @@
.half-modal {
float: left;
margin-right: 1%;
margin-right: 2%;
width: 49%;
&:last-of-type {
&:nth-of-type(2) {
margin: 0;
}
label {
display: inline-block;
margin-top: 1em;
}
}
.no-bottom-margin {
@ -44,6 +46,105 @@
}
}
.categories {
[type="text"] {
width: calc(100% - 84px);
}
[type="color"] {
cursor: pointer;
height: 36px;
margin-left: 2px;
vertical-align: bottom;
width: 36px;
}
}
.issue-trackers {
label {
display: inline-block;
margin-top: 1em;
}
[type="text"] {
&:first-of-type {
width: 380px;
}
&:last-of-type {
margin-left: 2px;
width: 148px;
}
}
button {
height: 36px;
margin-left: 2px;
padding: 9px;
vertical-align: top;
}
}
.users {
label {
display: inline-block;
margin-top: 1em;
}
}
.gu-mirror {
@include shadow-high;
background: $white;
display: block;
// To override default opacity settings
filter: alpha(opacity=100);
opacity: 1;
.actions {
float: right;
}
}
.modal-list {
border: 1px solid $color-border;
border-radius: 3px;
list-style: none;
margin: 0;
margin-bottom: 1em;
padding: 0;
li {
border-bottom: 1px solid $color-border;
padding: 0 7px;
&:last-of-type {
border: 0;
}
}
.actions {
float: right;
}
.badge {
margin-right: 5px;
}
.icon-trash-empty,
.icon-edit {
cursor: pointer;
}
}
.icon-resize-vertical {
border-right: 1px solid $color-border;
cursor: move;
margin-left: -5px;
margin-right: .5em;
width: 1.5em;
}
section {
ul {
border: 1px solid lighten($color-border, 10%);
@ -66,7 +167,7 @@
.badge {
float: right;
margin-top: 4px;
margin-top: 3px;
}
}

View File

@ -11,6 +11,9 @@
@import 'chartist-settings';
@import 'chartist';
// dragula
@import '../../node_modules/dragula/dist/dragula.css';
// Local styles
@import 'core';
@import 'login';

View File

@ -1,13 +1,16 @@
(function(global) {
var map = {
'app': 'build',
'rxjs': 'node_modules/rxjs',
'@angular': 'node_modules/@angular'
'app': 'build',
'dragula': 'node_modules/dragula/dist/dragula.js',
'ng2-dragula': 'node_modules/ng2-dragula',
'rxjs': 'node_modules/rxjs',
'@angular': 'node_modules/@angular'
};
var packages = {
'app': { main: 'main.js', defaultExtension: 'js' },
'rxjs': { defaultExtension: 'js' }
'app': { main: 'main.js', defaultExtension: 'js' },
'rxjs': { defaultExtension: 'js' },
'ng2-dragula': { defaultExtension: 'js' }
};
var angularPackages = [