diff --git a/package-lock.json b/package-lock.json
index a4ba78d7..9cbe3f59 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5941,6 +5941,11 @@
"integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=",
"dev": true
},
+ "md2": {
+ "version": "0.0.28",
+ "resolved": "https://registry.npmjs.org/md2/-/md2-0.0.28.tgz",
+ "integrity": "sha512-XQ71eTVKG3oRsGBj3lMLqL8p2inueqDXn++a2EntzWkUPlBZXPCPtlpfI9ER/LAlBKwJZQSqTzFItw7q9+vgvw=="
+ },
"md5.js": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz",
diff --git a/package.json b/package.json
index 5a93b00e..acf4eda4 100644
--- a/package.json
+++ b/package.json
@@ -35,6 +35,7 @@
"hammerjs": "^2.0.8",
"highlight.js": "^9.12.0",
"intl": "^1.2.5",
+ "md2": "0.0.28",
"moment": "^2.18.1",
"ngx-color-picker": "^4.3.1",
"ngx-perfect-scrollbar": "^4.5.6",
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index a7621b15..e95f851b 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -43,6 +43,10 @@ const appRoutes: Routes = [
path : 'apps/contacts',
loadChildren: './main/content/apps/contacts/contacts.module#FuseContactsModule'
},
+ {
+ path : 'apps/scrumboard',
+ loadChildren: './main/content/apps/scrumboard/scrumboard.module#FuseScrumboardModule'
+ },
{
path : '**',
redirectTo: 'apps/dashboards/project'
@@ -73,7 +77,7 @@ const appRoutes: Routes = [
UIModule,
ComponentsModule
],
- providers: [
+ providers : [
FuseSplashScreenService,
FuseConfigService
],
diff --git a/src/app/core/fuseUtils.ts b/src/app/core/fuseUtils.ts
index 228d0353..3278c1a6 100644
--- a/src/app/core/fuseUtils.ts
+++ b/src/app/core/fuseUtils.ts
@@ -90,4 +90,16 @@ export class FuseUtils
return (S4() + S4());
}
+
+ public static toggleInArray(item, array)
+ {
+ if ( array.indexOf(item) === -1 )
+ {
+ array.push(item);
+ }
+ else
+ {
+ array.splice(array.indexOf(item), 1);
+ }
+ }
}
diff --git a/src/app/core/modules/shared.module.ts b/src/app/core/modules/shared.module.ts
index f9c6acea..60b1d106 100644
--- a/src/app/core/modules/shared.module.ts
+++ b/src/app/core/modules/shared.module.ts
@@ -20,6 +20,7 @@ import { FuseMdSidenavHelperService } from '../directives/md-sidenav-helper/md-s
import { FuseHljsComponent } from '../components/hljs/hljs.component';
import { FuseIfOnDomDirective } from '../directives/fuse-if-on-dom/fuse-if-on-dom.directive';
import { FuseMaterialColorPickerComponent } from '../components/material-color-picker/material-color-picker.component';
+import { Md2Module } from 'md2';
@NgModule({
declarations : [
@@ -41,7 +42,8 @@ import { FuseMaterialColorPickerComponent } from '../components/material-color-p
ReactiveFormsModule,
ColorPickerModule,
NgxDnDModule,
- NgxDatatableModule
+ NgxDatatableModule,
+ Md2Module
],
exports : [
FlexLayoutModule,
@@ -59,7 +61,8 @@ import { FuseMaterialColorPickerComponent } from '../components/material-color-p
NgxDnDModule,
NgxDatatableModule,
FuseIfOnDomDirective,
- FuseMaterialColorPickerComponent
+ FuseMaterialColorPickerComponent,
+ Md2Module
],
entryComponents: [
FuseConfirmDialogComponent
diff --git a/src/app/core/pipes/getById.pipe.ts b/src/app/core/pipes/getById.pipe.ts
index e2797aad..5993697f 100644
--- a/src/app/core/pipes/getById.pipe.ts
+++ b/src/app/core/pipes/getById.pipe.ts
@@ -1,6 +1,9 @@
import { Pipe, PipeTransform } from '@angular/core';
-@Pipe({name: 'getById'})
+@Pipe({
+ name: 'getById',
+ pure: false
+})
export class GetByIdPipe implements PipeTransform
{
transform(value: any[], id: number, property: string): any
diff --git a/src/app/core/scss/partials/_colors.scss b/src/app/core/scss/partials/_colors.scss
index 6a92fe6d..7d61345f 100644
--- a/src/app/core/scss/partials/_colors.scss
+++ b/src/app/core/scss/partials/_colors.scss
@@ -54,7 +54,8 @@ $matColorHues: 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, A100, A200, A400
&.secondary-text,
.secondary-text,
.mat-icon,
- .icon {
+ .icon,
+ .md2-datepicker-button {
color: rgba(0, 0, 0, 0.54);
}
@@ -79,7 +80,8 @@ $matColorHues: 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, A100, A200, A400
@else {
.mat-icon,
- .icon {
+ .icon,
+ .md2-datepicker-button {
color: rgba(255, 255, 255, 1);
}
diff --git a/src/app/fuse-fake-db/fuse-fake-db.service.ts b/src/app/fuse-fake-db/fuse-fake-db.service.ts
index 736b6ef6..4f9bbec1 100644
--- a/src/app/fuse-fake-db/fuse-fake-db.service.ts
+++ b/src/app/fuse-fake-db/fuse-fake-db.service.ts
@@ -12,6 +12,7 @@ import { SearchFakeDb } from './search';
import { QuickPanelFakeDb } from './quick-panel';
import { IconsFakeDb } from './icons';
import { ProjectsDashboardDb } from './projects-dashboard';
+import { ScrumboardFakeDb } from './scrumboard';
export class FuseFakeDbService implements InMemoryDbService
{
@@ -42,7 +43,8 @@ export class FuseFakeDbService implements InMemoryDbService
'quick-panel-events' : QuickPanelFakeDb.events,
'icons' : IconsFakeDb.icons,
'projects-dashboard-projects': ProjectsDashboardDb.projects,
- 'projects-dashboard-widgets' : ProjectsDashboardDb.widgets
+ 'projects-dashboard-widgets' : ProjectsDashboardDb.widgets,
+ 'scrumboard-boards' : ScrumboardFakeDb.boards
};
}
}
diff --git a/src/app/fuse-fake-db/scrumboard.ts b/src/app/fuse-fake-db/scrumboard.ts
new file mode 100644
index 00000000..aac7d95b
--- /dev/null
+++ b/src/app/fuse-fake-db/scrumboard.ts
@@ -0,0 +1,787 @@
+export class ScrumboardFakeDb
+{
+ public static boards = [
+ {
+ 'id' : '32gfhaf2',
+ 'name' : 'ACME Frontend Application',
+ 'uri' : 'acme-frontend-application',
+ 'settings': {
+ 'color' : 'fuse-dark',
+ 'subscribed' : false,
+ 'cardCoverImages': true
+ },
+ 'lists' : [
+ {
+ 'id' : '56027cf5a2ca3839a5d36103',
+ 'name' : 'Design',
+ 'idCards': [
+ '5603a2a3cab0c8300f6096b3',
+ '44d1.2b51ea6cc2b5d.21f4a3412e857.8ffa2d8b44ad9.ac87215ed53a1.67d4921ad8f8d.9f318bcb2'
+ ]
+ },
+ {
+ 'id' : '56127cf2a2ca3539g7d36103',
+ 'name' : 'Development',
+ 'idCards': [
+ '2837273da9b93dd84243s0f9',
+ '5787b7e4740c57bf0dffd5b6',
+ '5637273da9b93bb84743a0f9',
+ '7987.9740ba532b0d4.f9d12243f7362.507c0738dc561.87fba0a03df6e.75e6508cacf10.7a9835b54'
+ ]
+ },
+ {
+ 'id' : 'faf244627326f1249525763d',
+ 'name' : 'Upcoming Features',
+ 'idCards': [
+ 'd9005a4b89ed2aadca48a6ad',
+ 'f6b9d7a9247e5d794a081927',
+ '80ed.24ad3b18e2668.f28fbbceeeff9.5a834620a42f1.5909be19a2bf2.6c4a54947ce2d.da356b0c1',
+ '0ad2.7862f947bc456.f42b446df54cb.d1dd9e93601a1.9deb1406d1404.0b3c278fc7001.733341b42',
+ 'bad3.51be8ad33acaf.9540ecb37f7e8.6bee596cfe7d3.44c68bee289c4.b96ed0b9f0af7.e14846035'
+ ]
+ },
+ {
+ 'id' : 'ad7d.9fffac5dff412.c83bca6853767.8fd7549b2b1ca.ceda8a01774c4.a5cf3976e87e4.ce79eeeea',
+ 'name' : 'Known Bugs',
+ 'idCards': [
+ 'acc6.9c673cd2f5e35.521e91d8d5991.4b2a95e0539d1.027930c0743c5.7ad1ea7bea476.e8fbe6347',
+ '3279.3d69b40cc0b75.690252b6bea08.1e1789b0b7c2e.2f264b8661ce2.84d5f56910e23.429be5e8a',
+ 'ba01.8e1a43f92a03a.0022bd5cbb9ba.275c64d911d8c.880e0846a3966.f75ff43e53ad.48ad612e7'
+ ]
+ }
+ ],
+ 'cards' : [
+ {
+ 'id' : '2837273da9b93dd84243s0f9',
+ 'name' : 'Update generators',
+ 'description' : 'Current generator doesn\'t support Node.js 6 and above.',
+ 'idAttachmentCover': '',
+ 'idMembers' : [
+ '26027s1930450d8bf7b10828'
+ ],
+ 'idLabels' : [
+ '26022e4129ad3a5sc28b36cd'
+ ],
+ 'attachments' : [],
+ 'subscribed' : false,
+ 'checklists' : [],
+ 'checkItems' : 0,
+ 'checkItemsChecked': 0,
+ 'comments' : [
+ {
+ 'idMember': '36027j1930450d8bf7b10158',
+ 'message' : 'AngularCLI could be a nice alternative.',
+ 'time' : 'now'
+ }
+ ],
+ 'activities' : [],
+ 'due' : null
+ },
+ {
+ 'id' : '5603a2a3cab0c8300f6096b3',
+ 'name' : 'Change background colors',
+ 'description' : '',
+ 'idAttachmentCover': '67027cahbe3b52ecf2dc631c',
+ 'idMembers' : [
+ '76027g1930450d8bf7b10958'
+ ],
+ 'idLabels' : [
+ '56027e4119ad3a5dc28b36cd',
+ '5640635e19ad3a5dc21416b2'
+ ],
+ 'attachments' : [
+ {
+ 'id' : '67027cahbe3b52ecf2dc631c',
+ 'name': 'mail.jpg',
+ 'src' : 'assets/images/scrumboard/mail.jpg',
+ 'time': 'Added Nov 3 at 15:22AM',
+ 'type': 'image'
+ },
+ {
+ 'id' : '56027cfcbe1b72ecf1fc452a',
+ 'name': 'calendar.jpg',
+ 'src' : 'assets/images/scrumboard/calendar.jpg',
+ 'time': 'Added Nov 1 at 12:34PM',
+ 'type': 'image'
+ }
+ ],
+ 'subscribed' : true,
+ 'checklists' : [
+ {
+ 'id' : '63021cfdbe1x72wcf1fc451v',
+ 'name' : 'Checklist',
+ 'checkItemsChecked': 1,
+ 'checkItems' : [
+ {
+ 'name' : 'Implement a calendar library',
+ 'checked': false
+ },
+ {
+ 'name' : 'Replace event colors with Material Design colors',
+ 'checked': true
+ },
+ {
+ 'name' : 'Replace icons with Material Design icons',
+ 'checked': false
+ },
+ {
+ 'name' : 'Use moment.js',
+ 'checked': false
+ }
+ ]
+ },
+ {
+ 'name' : 'Checklist 2',
+ 'id' : '74031cfdbe1x72wcz1dc166z',
+ 'checkItemsChecked': 1,
+ 'checkItems' : [
+ {
+ 'name' : 'Replace event colors with Material Design colors',
+ 'checked': true
+ },
+ {
+ 'name' : 'Replace icons with Material Design icons',
+ 'checked': false
+ },
+ {
+ 'name' : 'Use moment.js',
+ 'checked': false
+ }
+ ]
+ }
+ ],
+ 'checkItems' : 7,
+ 'checkItemsChecked': 2,
+ 'comments' : [
+ {
+ 'idMember': '56027c1930450d8bf7b10758',
+ 'message' : 'We should be able to add moment.js without any problems',
+ 'time' : '12 mins. ago'
+ },
+ {
+ 'idMember': '36027j1930450d8bf7b10158',
+ 'message' : 'I added a link for a page that might help us deciding the colors',
+ 'time' : '30 mins. ago'
+ }
+ ],
+ 'activities' : [
+ {
+ 'idMember': '56027c1930450d8bf7b10758',
+ 'message' : 'added a comment',
+ 'time' : '12 mins. ago'
+ },
+ {
+ 'idMember': '36027j1930450d8bf7b10158',
+ 'message' : 'added a comment',
+ 'time' : '30 mins. ago'
+ },
+ {
+ 'idMember': '36027j1930450d8bf7b10158',
+ 'message' : 'attached a link',
+ 'time' : '45 mins. ago'
+ }
+ ],
+ 'due' : 'Tue Aug 29 2017 13:16:34 GMT+0300 (Turkey Standard Time)'
+ },
+ {
+ 'id' : '5637273da9b93bb84743a0f9',
+ 'name' : 'Fix splash screen bugs',
+ 'description' : '',
+ 'idAttachmentCover': '',
+ 'idMembers' : [
+ '56027c1930450d8bf7b10758'
+ ],
+ 'idLabels' : [
+ '5640635e19ad3a5dc21416b2'
+ ],
+ 'attachments' : [],
+ 'subscribed' : true,
+ 'checklists' : [],
+ 'checkItems' : 0,
+ 'checkItemsChecked': 0,
+ 'comments' : [],
+ 'activities' : [],
+ 'due' : null
+ },
+ {
+ 'id' : 'd9005a4b89ed2aadca48a6ad',
+ 'name' : 'Add alternative authentication pages',
+ 'description' : '',
+ 'idAttachmentCover': '',
+ 'idMembers' : [
+ '36027j1930450d8bf7b10158'
+ ],
+ 'idLabels' : [
+ '6540635g19ad3s5dc31412b2',
+ '56027e4119ad3a5dc28b36cd'
+ ],
+ 'attachments' : [],
+ 'subscribed' : false,
+ 'checklists' : [
+ {
+ 'id' : 'dbfb.99bd0ad37dabc.e05046f0c824d.18f26bb524c96.78bebc8488634.240c0ee6a5e45.4cb872965',
+ 'name' : 'Pages',
+ 'checkItemsChecked': 2,
+ 'checkItems' : [
+ {
+ 'name' : 'Login',
+ 'checked': true
+ },
+ {
+ 'name' : 'Register',
+ 'checked': true
+ },
+ {
+ 'name' : 'Lost Password',
+ 'checked': false
+ },
+ {
+ 'name' : 'Recover Password',
+ 'checked': false
+ },
+ {
+ 'name' : 'Activate Account',
+ 'checked': false
+ }
+ ]
+ }
+ ],
+ 'checkItems' : 5,
+ 'checkItemsChecked': 2,
+ 'comments' : [],
+ 'activities' : [],
+ 'due' : null
+ },
+ {
+ 'id' : '5787b7e4740c57bf0dffd5b6',
+ 'name' : 'Fix the console',
+ 'description' : 'We need to fix the console asap!',
+ 'idAttachmentCover': '',
+ 'idMembers' : [],
+ 'idLabels' : [
+ '26022e4129ad3a5sc28b36cd'
+ ],
+ 'attachments' : [],
+ 'subscribed' : true,
+ 'checklists' : [],
+ 'checkItems' : 0,
+ 'checkItemsChecked': 0,
+ 'comments' : [
+ {
+ 'idMember': '36027j1930450d8bf7b10158',
+ 'message' : 'I\'m on it!',
+ 'time' : 'now'
+ }
+ ],
+ 'activities' : [],
+ 'due' : 'Fri Sep 07 2018 15:00:00 GMT+0300 (Turkey Standard Time)'
+ },
+ {
+ 'id' : 'f6b9d7a9247e5d794a081927',
+ 'name' : 'New media player',
+ 'description' : '',
+ 'idAttachmentCover': '',
+ 'idMembers' : [
+ '76027g1930450d8bf7b10958',
+ '56027c1930450d8bf7b10758',
+ '26027s1930450d8bf7b10828'
+ ],
+ 'idLabels' : [
+ '5640635e19ad3a5dc21416b2',
+ '6540635g19ad3s5dc31412b2'
+ ],
+ 'attachments' : [],
+ 'subscribed' : false,
+ 'checklists' : [],
+ 'checkItems' : 0,
+ 'checkItemsChecked': 0,
+ 'comments' : [],
+ 'activities' : [],
+ 'due' : null
+ },
+ {
+ 'id' : 'acc6.9c673cd2f5e35.521e91d8d5991.4b2a95e0539d1.027930c0743c5.7ad1ea7bea476.e8fbe6347',
+ 'name' : 'Memory Leak',
+ 'description' : '',
+ 'idAttachmentCover': '',
+ 'idMembers' : [
+ '36027j1930450d8bf7b10158'
+ ],
+ 'idLabels' : [
+ '26022e4129ad3a5sc28b36cd',
+ '5640635e19ad3a5dc21416b2'
+ ],
+ 'attachments' : [],
+ 'subscribed' : false,
+ 'checklists' : [],
+ 'checkItems' : 0,
+ 'checkItemsChecked': 0,
+ 'comments' : [],
+ 'activities' : [],
+ 'due' : null
+ },
+ {
+ 'id' : '3279.3d69b40cc0b75.690252b6bea08.1e1789b0b7c2e.2f264b8661ce2.84d5f56910e23.429be5e8a',
+ 'name' : 'Broken toolbar on profile page',
+ 'description' : '',
+ 'idAttachmentCover': '',
+ 'idMembers' : [
+ '26027s1930450d8bf7b10828'
+ ],
+ 'idLabels' : [
+ '26022e4129ad3a5sc28b36cd'
+ ],
+ 'attachments' : [],
+ 'subscribed' : false,
+ 'checklists' : [],
+ 'checkItems' : 0,
+ 'checkItemsChecked': 0,
+ 'comments' : [
+ {
+ 'idMember': '36027j1930450d8bf7b10158',
+ 'message' : 'This should be a medium priority bug, shouldn\'t it?',
+ 'time' : 'now'
+ }
+ ],
+ 'activities' : [],
+ 'due' : null
+ },
+ {
+ 'id' : 'ba01.8e1a43f92a03a.0022bd5cbb9ba.275c64d911d8c.880e0846a3966.f75ff43e53ad.48ad612e7',
+ 'name' : 'Button hover style',
+ 'description' : 'If there are 3 or more buttons in certain page, weird flashing happens when you hover over the red ones.',
+ 'idAttachmentCover': '',
+ 'idMembers' : [
+ '26027s1930450d8bf7b10828'
+ ],
+ 'idLabels' : [
+ '26022e4129ad3a5sc28b36cd',
+ '5640635e19ad3a5dc21416b2'
+ ],
+ 'attachments' : [],
+ 'subscribed' : true,
+ 'checklists' : [],
+ 'checkItems' : 0,
+ 'checkItemsChecked': 0,
+ 'comments' : [],
+ 'activities' : [],
+ 'due' : 'Wed Mar 08 2017 12:00:00 GMT+0300 (Turkey Standard Time)'
+ },
+ {
+ 'id' : '80ed.24ad3b18e2668.f28fbbceeeff9.5a834620a42f1.5909be19a2bf2.6c4a54947ce2d.da356b0c1',
+ 'name' : 'New header designs',
+ 'description' : '',
+ 'idAttachmentCover': '12027cafbe3b52ecf2ef632c',
+ 'idMembers' : [],
+ 'idLabels' : [
+ '56027e4119ad3a5dc28b36cd',
+ '6540635g19ad3s5dc31412b2',
+ '5640635e19ad3a5dc21416b2'
+ ],
+ 'attachments' : [
+ {
+ 'id' : '12027cafbe3b52ecf2ef632c',
+ 'name': 'header-.jpg',
+ 'src' : 'assets/images/scrumboard/header-1.jpg',
+ 'time': 'Added Nov 3 at 15:22AM',
+ 'type': 'image'
+ },
+ {
+ 'id' : '55027ced1e1a12ecf1fced2a',
+ 'name': 'header-2.jpg',
+ 'src' : 'assets/images/scrumboard/header-2.jpg',
+ 'time': 'Added Nov 1 at 12:34PM',
+ 'type': 'image'
+ }
+ ],
+ 'subscribed' : false,
+ 'checklists' : [],
+ 'checkItems' : 0,
+ 'checkItemsChecked': 0,
+ 'comments' : [
+ {
+ 'idMember': '36027j1930450d8bf7b10158',
+ 'message' : 'Currently we have two new designs ready to ship.',
+ 'time' : 'now'
+ }
+ ],
+ 'activities' : [],
+ 'due' : null
+ },
+ {
+ 'id' : '0ad2.7862f947bc456.f42b446df54cb.d1dd9e93601a1.9deb1406d1404.0b3c278fc7001.733341b42',
+ 'name' : 'Fixed footer',
+ 'description' : '',
+ 'idAttachmentCover': '',
+ 'idMembers' : [
+ '26027s1930450d8bf7b10828',
+ '56027c1930450d8bf7b10758'
+ ],
+ 'idLabels' : [
+ '6540635g19ad3s5dc31412b2'
+ ],
+ 'attachments' : [],
+ 'subscribed' : true,
+ 'checklists' : [],
+ 'checkItems' : 0,
+ 'checkItemsChecked': 0,
+ 'comments' : [],
+ 'activities' : [],
+ 'due' : null
+ },
+ {
+ 'id' : 'bad3.51be8ad33acaf.9540ecb37f7e8.6bee596cfe7d3.44c68bee289c4.b96ed0b9f0af7.e14846035',
+ 'name' : 'Collapsable navigation',
+ 'description' : '',
+ 'idAttachmentCover': '',
+ 'idMembers' : [],
+ 'idLabels' : [
+ '6540635g19ad3s5dc31412b2'
+ ],
+ 'attachments' : [],
+ 'subscribed' : false,
+ 'checklists' : [],
+ 'checkItems' : 0,
+ 'checkItemsChecked': 0,
+ 'comments' : [
+ {
+ 'idMember': '36027j1930450d8bf7b10158',
+ 'message' : 'I\'m not sure why we re-doing the navigation. The current collapsable navigation works flawlessly.',
+ 'time' : 'now'
+ }
+ ],
+ 'activities' : [],
+ 'due' : null
+ },
+ {
+ 'id' : '44d1.2b51ea6cc2b5d.21f4a3412e857.8ffa2d8b44ad9.ac87215ed53a1.67d4921ad8f8d.9f318bcb2',
+ 'name' : 'Mail app new layout',
+ 'description' : 'Current layout has lots of flaws in mobile. Outlook view should help with that.',
+ 'idAttachmentCover': '',
+ 'idMembers' : [
+ '56027c1930450d8bf7b10758',
+ '26027s1930450d8bf7b10828',
+ '76027g1930450d8bf7b10958',
+ '36027j1930450d8bf7b10158'
+ ],
+ 'idLabels' : [
+ '56027e4119ad3a5dc28b36cd',
+ '26022e4129ad3a5sc28b36cd'
+ ],
+ 'attachments' : [],
+ 'subscribed' : false,
+ 'checklists' : [],
+ 'checkItems' : 0,
+ 'checkItemsChecked': 0,
+ 'comments' : [],
+ 'activities' : [],
+ 'due' : null
+ },
+ {
+ 'id' : '7987.9740ba532b0d4.f9d12243f7362.507c0738dc561.87fba0a03df6e.75e6508cacf10.7a9835b54',
+ 'name' : 'API recover and monitoring',
+ 'description' : 'We need a service to monitor and recover failed APIs.',
+ 'idAttachmentCover': '',
+ 'idMembers' : [
+ '36027j1930450d8bf7b10158',
+ '76027g1930450d8bf7b10958'
+ ],
+ 'idLabels' : [
+ '26022e4129ad3a5sc28b36cd',
+ '5640635e19ad3a5dc21416b2'
+ ],
+ 'attachments' : [],
+ 'subscribed' : true,
+ 'checklists' : [
+ {
+ 'id' : '6926.2b31d119e4a.889401e0ca7a0.13ad8ce2e569d.976e54e8b5d87.456afccd7e820.d6c77106a',
+ 'name' : 'API Monitoring',
+ 'checkItemsChecked': 2,
+ 'checkItems' : [
+ {
+ 'name' : 'Simple dashboard design',
+ 'checked': false
+ },
+ {
+ 'name' : 'Should be able to see different time periods on the same dashboard',
+ 'checked': true
+ },
+ {
+ 'name' : 'Different colors for different clusters',
+ 'checked': true
+ }
+ ]
+ },
+ {
+ 'id' : '7c22.5261c7924387f.248e8b1d32205.003f7a9f501d1.1d48dcdbe8b23.8099dcc5f75a7.29a966196',
+ 'name' : 'API Recovery',
+ 'checkItemsChecked': 1,
+ 'checkItems' : [
+ {
+ 'name' : 'Warning notifications to all developers',
+ 'checked': false
+ },
+ {
+ 'name' : 'Immediate recovery options attached to the notifications',
+ 'checked': true
+ },
+ {
+ 'name' : 'Backups every 6hours',
+ 'checked': false
+ }
+ ]
+ }
+ ],
+ 'checkItems' : 6,
+ 'checkItemsChecked': 3,
+ 'comments' : [],
+ 'activities' : [],
+ 'due' : 'Fri Feb 02 2017 14:20:34 GMT+0300 (Turkey Standard Time)'
+ }
+ ],
+ 'members' : [
+ {
+ 'id' : '56027c1930450d8bf7b10758',
+ 'name' : 'Alice Freeman',
+ 'avatar': 'assets/images/avatars/alice.jpg'
+ },
+ {
+ 'id' : '26027s1930450d8bf7b10828',
+ 'name' : 'Danielle Obrien',
+ 'avatar': 'assets/images/avatars/danielle.jpg'
+ },
+ {
+ 'id' : '76027g1930450d8bf7b10958',
+ 'name' : 'James Lewis',
+ 'avatar': 'assets/images/avatars/james.jpg'
+ },
+ {
+ 'id' : '36027j1930450d8bf7b10158',
+ 'name' : 'Vincent Munoz',
+ 'avatar': 'assets/images/avatars/vincent.jpg'
+ }
+ ],
+ 'labels' : [
+ {
+ 'id' : '26022e4129ad3a5sc28b36cd',
+ 'name' : 'High Priority',
+ 'color': 'md-red-500-bg'
+ },
+ {
+ 'id' : '56027e4119ad3a5dc28b36cd',
+ 'name' : 'Design',
+ 'color': 'md-orange-400-bg'
+ },
+ {
+ 'id' : '5640635e19ad3a5dc21416b2',
+ 'name' : 'App',
+ 'color': 'md-blue-600-bg'
+ },
+ {
+ 'id' : '6540635g19ad3s5dc31412b2',
+ 'name' : 'Feature',
+ 'color': 'md-green-400-bg'
+ }
+ ]
+ },
+ {
+ 'id' : '27cfcbe1',
+ 'name' : 'ACME Backend Application',
+ 'uri' : 'acme-backend-application',
+ 'settings': {
+ 'color' : 'blue-grey',
+ 'subscribed' : false,
+ 'cardCoverImages': true
+ },
+ 'lists' : [
+ {
+ 'id' : '56027cf5a2ca3839a5d36103',
+ 'name' : 'Designs',
+ 'idCards': [
+ '5603a2a3cab0c8300f6096b3'
+ ]
+ },
+ {
+ 'id' : '56127cf2a2ca3539g7d36103',
+ 'name' : 'Development',
+ 'idCards': [
+ '5637273da9b93bb84743a0f9'
+ ]
+ }
+ ],
+ 'cards' : [
+ {
+ 'id' : '5603a2a3cab0c8300f6096b3',
+ 'name' : 'Calendar App Design',
+ 'description' : '',
+ 'idAttachmentCover': '56027cfcbe1b72ecf1fc452a',
+ 'idMembers' : [
+ '56027c1930450d8bf7b10758',
+ '36027j1930450d8bf7b10158'
+ ],
+ 'idLabels' : [
+ '56027e4119ad3a5dc28b36cd',
+ '5640635e19ad3a5dc21416b2'
+ ],
+ 'attachments' : [
+ {
+ 'id' : '56027cfcbe1b72ecf1fc452a',
+ 'name': 'calendar-app-design.jpg',
+ 'src' : 'assets/images/scrumboard/calendar.jpg',
+ 'time': 'Added Nov 1 at 12:34PM',
+ 'type': 'image'
+ },
+ {
+ 'id' : '67027cahbe3b52ecf2dc631c',
+ 'url' : 'assets/images/scrumboard/calendar.jpg',
+ 'time': 'Added Nov 3 at 15:22AM',
+ 'type': 'link'
+ }
+ ],
+ 'subscribed' : true,
+ 'checklists' : [
+ {
+ 'id' : '63021cfdbe1x72wcf1fc451v',
+ 'name' : 'Checklist',
+ 'checkItemsChecked': 1,
+ 'checkItems' : [
+ {
+ 'name' : 'Implement a calendar library',
+ 'checked': false
+ },
+ {
+ 'name' : 'Replace event colors with Material Design colors',
+ 'checked': true
+ },
+ {
+ 'name' : 'Replace icons with Material Design icons',
+ 'checked': false
+ },
+ {
+ 'name' : 'Use moment.js',
+ 'checked': false
+ }
+ ]
+ },
+ {
+ 'name' : 'Checklist 2',
+ 'id' : '74031cfdbe1x72wcz1dc166z',
+ 'checkItemsChecked': 1,
+ 'checkItems' : [
+ {
+ 'name' : 'Replace event colors with Material Design colors',
+ 'checked': true
+ },
+ {
+ 'name' : 'Replace icons with Material Design icons',
+ 'checked': false
+ },
+ {
+ 'name' : 'Use moment.js',
+ 'checked': false
+ }
+ ]
+ }
+ ],
+ 'checkItems' : 7,
+ 'checkItemsChecked': 2,
+ 'comments' : [
+ {
+ 'idMember': '56027c1930450d8bf7b10758',
+ 'message' : 'We should be able to add moment.js without any problems',
+ 'time' : '12 mins. ago'
+ },
+ {
+ 'idMember': '36027j1930450d8bf7b10158',
+ 'message' : 'I added a link for a page that might help us deciding the colors',
+ 'time' : '30 mins. ago'
+ }
+ ],
+ 'activities' : [
+ {
+ 'idMember': '56027c1930450d8bf7b10758',
+ 'message' : 'added a comment',
+ 'time' : '12 mins. ago'
+ },
+ {
+ 'idMember': '36027j1930450d8bf7b10158',
+ 'message' : 'added a comment',
+ 'time' : '30 mins. ago'
+ },
+ {
+ 'idMember': '36027j1930450d8bf7b10158',
+ 'message' : 'attached a link',
+ 'time' : '45 mins. ago'
+ }
+ ],
+ 'due' : null
+ },
+ {
+ 'id' : '5637273da9b93bb84743a0f9',
+ 'name' : 'Fix Splash Screen bugs',
+ 'description' : '',
+ 'idAttachmentCover': '5603a2ae2bbd55bb2db57478',
+ 'idMembers' : [
+ '56027c1930450d8bf7b10758'
+ ],
+ 'idLabels' : [],
+ 'attachments' : [
+ {
+ 'id' : '5603a2ae2bbd55bb2db57478',
+ 'name': 'mail-app-design.jpg',
+ 'src' : 'assets/images/scrumboard/mail.jpg',
+ 'time': 'Added Nov 1 at 12:34PM',
+ 'type': 'image'
+ }
+ ],
+ 'subscribed' : true,
+ 'checklists' : [],
+ 'checkItems' : 0,
+ 'checkItemsChecked': 0,
+ 'comments' : [],
+ 'activities' : [],
+ 'due' : null
+ }
+ ],
+ 'members' : [
+ {
+ 'id' : '56027c1930450d8bf7b10758',
+ 'name' : 'Alice Freeman',
+ 'avatar': 'assets/images/avatars/alice.jpg'
+ },
+ {
+ 'id' : '26027s1930450d8bf7b10828',
+ 'name' : 'Danielle Obrien',
+ 'avatar': 'assets/images/avatars/danielle.jpg'
+ },
+ {
+ 'id' : '76027g1930450d8bf7b10958',
+ 'name' : 'James Lewis',
+ 'avatar': 'assets/images/avatars/james.jpg'
+ },
+ {
+ 'id' : '36027j1930450d8bf7b10158',
+ 'name' : 'Vincent Munoz',
+ 'avatar': 'assets/images/avatars/vincent.jpg'
+ }
+ ],
+ 'labels' : [
+ {
+ 'id' : '56027e4119ad3a5dc28b36cd',
+ 'name' : 'Design',
+ 'color': 'md-red-500-bg'
+ },
+ {
+ 'id' : '5640635e19ad3a5dc21416b2',
+ 'name' : 'App',
+ 'color': 'md-blue-500-bg'
+ },
+ {
+ 'id' : '6540635g19ad3s5dc31412b2',
+ 'name' : 'Feature',
+ 'color': 'md-green-400-bg'
+ }
+ ]
+ }
+ ];
+}
diff --git a/src/app/main/content/apps/scrumboard/board/add-list/add-list.component.html b/src/app/main/content/apps/scrumboard/board/add-list/add-list.component.html
new file mode 100644
index 00000000..5103cd74
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/add-list/add-list.component.html
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
diff --git a/src/app/main/content/apps/scrumboard/board/add-list/add-list.component.scss b/src/app/main/content/apps/scrumboard/board/add-list/add-list.component.scss
new file mode 100644
index 00000000..9f53dafc
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/add-list/add-list.component.scss
@@ -0,0 +1,32 @@
+:host {
+ .new-list {
+ border-radius: 2px;
+ background-color: #EEF0F2;
+
+ .new-list-form-button {
+ text-transform: none;
+ font-size: 15px;
+ padding: 0 16px;
+ height: 64px;
+ margin: 0;
+ width: 100%;
+
+ md-icon {
+ border-radius: 50%;
+ height: 40px;
+ width: 40px;
+ line-height: 40px;
+ margin-right: 16px;
+ }
+ }
+
+ .new-list-form {
+ padding: 16px;
+ height: 64px;
+
+ > input {
+ height: 100%;
+ }
+ }
+ }
+}
diff --git a/src/app/main/content/apps/scrumboard/board/add-list/add-list.component.ts b/src/app/main/content/apps/scrumboard/board/add-list/add-list.component.ts
new file mode 100644
index 00000000..f0265579
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/add-list/add-list.component.ts
@@ -0,0 +1,57 @@
+import { Component, EventEmitter, Input, OnInit, Output, ViewChildren } from '@angular/core';
+import { FormBuilder, FormGroup } from '@angular/forms';
+
+@Component({
+ selector : 'fuse-scrumboard-board-add-list',
+ templateUrl: './add-list.component.html',
+ styleUrls : ['./add-list.component.scss']
+})
+export class FuseScrumboardBoardAddListComponent implements OnInit
+{
+ formActive = false;
+ form: FormGroup;
+ @Output() onlistAdd = new EventEmitter();
+ @ViewChildren('nameInput') nameInputField;
+
+ constructor(
+ private formBuilder: FormBuilder
+ )
+ {
+ }
+
+ ngOnInit()
+ {
+
+ }
+
+ openForm()
+ {
+ this.form = this.formBuilder.group({
+ name: ['']
+ });
+ this.formActive = true;
+ this.focusNameField();
+ }
+
+ closeForm()
+ {
+ this.formActive = false;
+ }
+
+ focusNameField()
+ {
+ setTimeout(() => {
+ this.nameInputField.first.nativeElement.focus();
+ });
+ }
+
+ onFormSubmit()
+ {
+ if ( this.form.valid )
+ {
+ this.onlistAdd.next(this.form.getRawValue().name);
+ this.formActive = false;
+ }
+ }
+
+}
diff --git a/src/app/main/content/apps/scrumboard/board/board.component.html b/src/app/main/content/apps/scrumboard/board/board.component.html
new file mode 100644
index 00000000..255efcf1
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/board.component.html
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/app/main/content/apps/scrumboard/board/board.component.scss b/src/app/main/content/apps/scrumboard/board/board.component.scss
new file mode 100644
index 00000000..8f805abf
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/board.component.scss
@@ -0,0 +1,151 @@
+@import "src/app/core/scss/fuse";
+
+:host {
+
+ md-sidenav-container {
+ width: 100%;
+ height: 100%;
+
+ md-sidenav {
+ width: 320px !important;
+ min-width: 320px !important;
+ max-width: 320px !important;
+ }
+
+ #board {
+ flex-direction: column;
+ display: flex;
+ height: 100%;
+
+ > .header {
+ position: relative;
+ height: 96px;
+ min-height: 96px;
+ max-height: 96px;
+ background-image: none;
+ z-index: 49;
+
+ .header-content {
+
+ .header-boards-button {
+ margin: 0;
+ }
+
+ .header-board-name {
+ font-size: 16px;
+
+ .board-subscribe {
+ margin-right: 8px;
+ }
+
+ .editable-buttons {
+
+ md-icon {
+ color: #FFFFFF !important;
+ }
+ }
+ }
+
+ .right-side {
+
+ > .md-button:last-child {
+ margin-right: 0;
+ }
+ }
+
+ }
+ }
+
+ #board-selector {
+ position: absolute;
+ top: 96px;
+ right: 0;
+ left: 0;
+ height: 192px;
+ z-index: 48;
+ padding: 24px;
+ opacity: 1;
+
+ .board-list-item {
+ width: 128px;
+ height: 192px;
+ padding: 16px;
+ cursor: pointer;
+ position: relative;
+
+ .board-name {
+ text-align: center;
+ padding: 16px 0;
+ }
+
+ .selected-icon {
+ position: absolute;
+ top: 0;
+ left: 50%;
+ width: 32px;
+ height: 32px;
+ margin-left: -16px;
+ border-radius: 50%;
+ text-align: center;
+ color: white;
+
+ i {
+ line-height: 32px !important;
+ }
+ }
+
+ &.add-new-board {
+ opacity: 0.6;
+ }
+ }
+ }
+
+ .board-content-wrapper {
+ position: relative;
+
+ .board-content {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ height: 100%;
+ background: #E5E7E8;
+ padding: 24px;
+ overflow-y: hidden;
+ overflow-x: auto;
+ -webkit-overflow-scrolling: touch;
+
+ .list-sortable-placeholder {
+ background: rgba(0, 0, 0, 0.06);
+ margin-right: 24px;
+ }
+
+ .new-list-wrapper {
+ width: 344px;
+ min-width: 344px;
+ max-width: 344px;
+ padding-right: 24px;
+ }
+
+ }
+ }
+ }
+ }
+}
+
+.is-mobile {
+
+ #board {
+
+ .list-card {
+
+ .list-card-sort-handle {
+ display: block;
+ }
+ }
+ }
+}
+
+.list-card-sort-helper {
+}
diff --git a/src/app/main/content/apps/scrumboard/board/board.component.ts b/src/app/main/content/apps/scrumboard/board/board.component.ts
new file mode 100644
index 00000000..9eecc068
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/board.component.ts
@@ -0,0 +1,60 @@
+import { Component, OnDestroy, OnInit } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+import { ScrumboardService } from '../scrumboard.service';
+import { Subscription } from 'rxjs/Subscription';
+import { FuseUtils } from '../../../../../core/fuseUtils';
+import { Location } from '@angular/common';
+
+@Component({
+ selector : 'fuse-scrumboard-board',
+ templateUrl: './board.component.html',
+ styleUrls : ['./board.component.scss']
+})
+export class FuseScrumboardBoardComponent implements OnInit, OnDestroy
+{
+ board: any;
+ onBoardChanged: Subscription;
+
+ constructor(
+ private route: ActivatedRoute,
+ private location: Location,
+ private scrumboardService: ScrumboardService
+ )
+ {
+ }
+
+ ngOnInit()
+ {
+ this.onBoardChanged =
+ this.scrumboardService.onBoardChanged
+ .subscribe(board => {
+ this.board = board;
+ });
+ }
+
+ onListAdd(newListName)
+ {
+ if ( newListName === '' )
+ {
+ return;
+ }
+ const newList = {
+ id : FuseUtils.generateGUID(),
+ name : newListName,
+ idCards: []
+ };
+
+ this.scrumboardService.addList(newList);
+ }
+
+ onBoardNameChanged(newName)
+ {
+ this.scrumboardService.updateBoard();
+ this.location.go('/apps/scrumboard/boards/' + this.board.id + '/' + this.board.uri);
+ }
+
+ ngOnDestroy()
+ {
+ this.onBoardChanged.unsubscribe();
+ }
+}
diff --git a/src/app/main/content/apps/scrumboard/board/dialogs/card/card.component.html b/src/app/main/content/apps/scrumboard/board/dialogs/card/card.component.html
new file mode 100644
index 00000000..857cb539
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/dialogs/card/card.component.html
@@ -0,0 +1,448 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{board.name}}
+ chevron_right
+ {{list.name}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
remove_red_eye
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{board.labels|getById:labelId:'name'}}
+ close
+
+
+
+
+
+
+
+
+
+
+
+ close
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{item.name}}
+ star
+
+
+
+
{{item.time}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ LINK
+
+
+ {{item.url}}
+ {{item.time}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{checklist.checkItemsChecked}} / {{checklist.checkItems.length}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{board.members| getById:activity.idMember:'name'}}
+
{{activity.message}}
+
{{activity.time}}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/app/main/content/apps/scrumboard/board/dialogs/card/card.component.scss b/src/app/main/content/apps/scrumboard/board/dialogs/card/card.component.scss
new file mode 100644
index 00000000..859c9927
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/dialogs/card/card.component.scss
@@ -0,0 +1,437 @@
+@import "src/app/core/scss/fuse";
+
+:host {
+ display: flex;
+ flex-direction: column;
+}
+
+.scrumboard-card-dialog {
+
+ .mat-dialog-container {
+ padding: 0;
+ width: 720px;
+
+ .mat-toolbar {
+
+ .due-date {
+
+ md2-datepicker {
+ min-width: initial;
+
+ .md2-datepicker-trigger {
+ padding: 0;
+
+ .md2-datepicker-button {
+ display: block;
+ position: relative;
+ top: 0;
+ left: 0;
+ line-height: normal;
+ }
+
+ .md2-datepicker-input {
+ display: none;
+ }
+ }
+ }
+ }
+ }
+
+ .mat-dialog-content {
+ position: relative;
+ background-color: #F5F5F5;
+
+ .card-breadcrumb {
+ font-weight: 500;
+ font-size: 14px;
+ }
+
+ .card-subscribe {
+ margin-right: 8px;
+ color: rgba(0, 0, 0, 0.6);
+ }
+
+ .picker {
+ width: 140px;
+ min-width: 140px;
+
+ }
+
+ .card-name {
+ width: 100%;
+ font-size: 24px;
+
+ .editable-input {
+ font-size: 24px;
+ }
+ }
+
+ .due-date {
+
+ md2-datepicker {
+ width: 180px;
+ min-width: 180px;
+
+ .md2-datepicker-trigger {
+ padding-top: 5px;
+ padding-bottom: 5px;
+
+ .md2-datepicker-button {
+ top: 0;
+ }
+
+ .md2-datepicker-input {
+ min-width: initial;
+ }
+ }
+ }
+
+ .remove-due-date {
+ }
+ }
+
+ .description {
+ padding-bottom: 16px;
+ }
+
+ .sections {
+
+ .section {
+ border-bottom: 1px solid rgba(0, 0, 0, 0.12);
+ margin-bottom: 32px;
+
+ &:last-child {
+ border-bottom: none;
+ margin-bottom: 0;
+
+ .section-content {
+ padding-bottom: 0;
+ }
+ }
+
+ .section-header {
+ font-size: 16px;
+
+ md-icon {
+ margin-right: 8px;
+ color: rgba(0, 0, 0, 0.6);
+ }
+
+ .section-title {
+ font-weight: 500;
+ }
+ }
+
+ .section-content {
+ padding: 24px 0 32px 0;
+ }
+
+ .labels {
+
+ .section-content {
+ padding: 8px 0 32px 0;
+ }
+
+ .label-chips {
+
+ box-shadow: none;
+ padding: 0;
+
+ .label-chip {
+ display: block;
+
+ .chip-remove {
+ cursor: pointer;
+ }
+ }
+ }
+ }
+
+ .members {
+
+ .section-content {
+ padding: 8px 0 32px 0;
+ }
+
+ .member-chips {
+ box-shadow: none;
+ padding: 0;
+
+ .member-chip {
+ padding: 4px 12px 4px 4px;
+
+ .member-chip-avatar {
+ width: 32px;
+ border-radius: 50%;
+ }
+
+ .chip-remove {
+ cursor: pointer;
+ }
+ }
+ }
+ }
+
+ .attachments {
+
+ .attachment {
+ margin-bottom: 16px;
+
+ .attachment-preview {
+ background-color: #EEF0F2;
+ width: 160px;
+ height: 128px;
+ background-size: contain;
+ background-position: 50% 50%;
+ background-repeat: no-repeat;
+ margin-right: 24px;
+ font-weight: 500;
+ color: rgba(0, 0, 0, 0.6);
+ }
+
+ .attachment-content {
+
+ .attachment-url,
+ .attachment-name {
+ font-weight: 500;
+ font-size: 16px;
+ }
+
+ .attachment-is-cover {
+ margin-left: 6px;
+ }
+
+ .attachment-time {
+ color: rgba(0, 0, 0, 0.6);
+ }
+
+ .attachment-actions-button {
+ background-color: white;
+ text-transform: capitalize;
+ margin: 12px 0 0 0;
+ padding-left: 12px;
+
+ md-icon {
+ margin-left: 8px;
+ color: rgba(0, 0, 0, 0.6);
+ }
+ }
+ }
+ }
+
+ .add-attachment-button {
+ margin: 0;
+
+ md-icon {
+ color: rgba(0, 0, 0, 0.6);
+ margin-right: 8px;
+ }
+
+ span {
+ font-weight: 500;
+ text-transform: capitalize;
+ }
+ }
+ }
+
+ .checklist {
+
+ .checklist-progress {
+ margin-bottom: 16px;
+
+ .checklist-progress-value {
+ margin-right: 12px;
+ font-weight: 500;
+ white-space: nowrap;
+ font-size: 14px;
+ }
+
+ .checklist-progressbar {
+ }
+ }
+
+ .editable-wrap {
+ flex: 1
+ }
+
+ .check-items {
+
+ .check-item {
+
+ md-checkbox {
+ margin-bottom: 0;
+
+ .md-label {
+ font-size: 14px;
+ }
+
+ &.md-checked {
+
+ .md-label {
+ text-decoration: line-through;
+ color: rgba(0, 0, 0, 0.6);
+ }
+ }
+ }
+ }
+ }
+
+ .new-check-item-form {
+ padding-top: 16px;
+
+ md-input-container {
+ margin: 0;
+ }
+
+ .md-button {
+ margin: 0 0 0 16px;
+ }
+ }
+ }
+
+ .comments {
+
+ .comment {
+ margin-bottom: 16px;
+
+ .comment-member-avatar {
+ width: 32px;
+ height: 32px;
+ border-radius: 50%;
+ margin-right: 16px;
+ }
+
+ .comment-member-name {
+ font-size: 14px;
+ font-weight: 500;
+ }
+
+ .comment-time {
+ font-size: 12px;
+ }
+
+ .comment-bubble {
+ position: relative;
+ padding: 8px;
+ background-color: white;
+ border: 1px solid rgb(220, 223, 225);
+ font-size: 14px;
+ margin: 4px 0;
+
+ &:after,
+ &:before {
+ content: ' ';
+ position: absolute;
+ width: 0;
+ height: 0;
+ }
+
+ &:after {
+ left: -7px;
+ right: auto;
+ top: 0px;
+ bottom: auto;
+ border: 11px solid;
+ border-color: white transparent transparent transparent;
+ }
+
+ &:before {
+ left: -9px;
+ right: auto;
+ top: -1px;
+ bottom: auto;
+ border: 8px solid;
+ border-color: rgb(220, 223, 225) transparent transparent transparent;
+ }
+ }
+
+ &.new-comment {
+
+ md-input-container {
+ margin: 0;
+ }
+ }
+ }
+ }
+
+ .activities {
+
+ .activity {
+ margin-bottom: 12px;
+
+ .activity-member-avatar {
+ width: 24px;
+ height: 24px;
+ border-radius: 50%;
+ margin-right: 16px;
+ }
+
+ .activity-member-name {
+ font-size: 14px;
+ font-weight: 500;
+ margin-right: 8px;
+ }
+
+ .activity-message {
+ font-size: 14px;
+ margin-right: 8px;
+ }
+
+ .activity-time {
+ font-size: 12px;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ }
+}
+
+.scrumboard-members-menu {
+ width: 240px;
+ .mat-checkbox-layout,
+ .mat-checkbox-label {
+ display: flex;
+ flex: 1;
+ }
+}
+
+.scrumboard-labels-menu {
+
+ .mat-menu-content {
+ padding-bottom: 0;
+
+ .mat-checkbox-layout,
+ .mat-checkbox-label {
+ display: flex;
+ flex: 1;
+ }
+
+ .views {
+ display: flex;
+ flex-direction: column;
+ position: relative;
+ overflow: hidden;
+ width: 240px;
+ min-width: 240px;
+ max-width: 240px;
+ min-height: 240px;
+
+ .view {
+ position: absolute;
+ width: 240px;
+ height: 100%;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ top: 0;
+
+ > .header {
+ border-bottom: 1px solid rgba(0, 0, 0, 0.1);
+ }
+ }
+ }
+ }
+}
diff --git a/src/app/main/content/apps/scrumboard/board/dialogs/card/card.component.ts b/src/app/main/content/apps/scrumboard/board/dialogs/card/card.component.ts
new file mode 100644
index 00000000..73d8b3eb
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/dialogs/card/card.component.ts
@@ -0,0 +1,262 @@
+import { Component, Inject, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
+import { MD_DIALOG_DATA, MdDialogRef, MdMenuTrigger } from '@angular/material';
+import { Subscription } from 'rxjs/Subscription';
+import { ScrumboardService } from '../../../scrumboard.service';
+import { NgForm } from '@angular/forms/src/forms';
+import { FuseUtils } from '../../../../../../../core/fuseUtils';
+
+@Component({
+ selector : 'fuse-scrumboard-board-card-dialog',
+ templateUrl : './card.component.html',
+ styleUrls : ['./card.component.scss'],
+ encapsulation: ViewEncapsulation.None
+})
+export class FuseScrumboardCardDialogComponent implements OnInit, OnDestroy
+{
+ card: any;
+ board: any;
+ list: any;
+
+ onBoardChanged: Subscription;
+ toggleInArray = FuseUtils.toggleInArray;
+
+ @ViewChild('checklistMenuTrigger') checklistMenu: MdMenuTrigger;
+ @ViewChild('newCheckListTitleField') newCheckListTitleField;
+
+ constructor(
+ public dialogRef: MdDialogRef,
+ @Inject(MD_DIALOG_DATA) private data: any,
+ private scrumboardService: ScrumboardService
+ )
+ {
+
+ }
+
+ ngOnInit()
+ {
+ this.onBoardChanged =
+ this.scrumboardService.onBoardChanged
+ .subscribe(board => {
+ this.board = board;
+
+ this.card = this.board.cards.find((_card) => {
+ return this.data.cardId === _card.id;
+ });
+
+ this.list = this.board.lists.find((_list) => {
+ return this.data.listId === _list.id;
+ });
+ });
+ }
+
+ /**
+ * Remove Due date
+ */
+ removeDueDate()
+ {
+ this.card.due = '';
+ this.updateCard();
+ }
+
+ /**
+ * Toggle Subscribe
+ */
+ toggleSubscribe()
+ {
+ this.card.subscribed = !this.card.subscribed;
+
+ this.updateCard();
+ }
+
+ /**
+ * Toggle Cover Image
+ * @param attachmentId
+ */
+ toggleCoverImage(attachmentId)
+ {
+ if ( this.card.idAttachmentCover === attachmentId )
+ {
+ this.card.idAttachmentCover = '';
+ }
+ else
+ {
+ this.card.idAttachmentCover = attachmentId;
+ }
+
+ this.updateCard();
+ }
+
+ /**
+ * Remove Attachment
+ * @param attachment
+ */
+ removeAttachment(attachment)
+ {
+ if ( attachment.id === this.card.idAttachmentCover )
+ {
+ this.card.idAttachmentCover = '';
+ }
+
+ this.card.attachments.splice(this.card.attachments.indexOf(attachment), 1);
+
+ this.updateCard();
+ }
+
+ /**
+ * Remove Checklist
+ * @param checklist
+ */
+ removeChecklist(checklist)
+ {
+ this.card.checklists.splice(this.card.checklists.indexOf(checklist), 1);
+
+ this.updateCard();
+ }
+
+ /**
+ * Update Checked Count
+ * @param list
+ */
+ updateCheckedCount(list)
+ {
+ const checkItems = list.checkItems;
+ let checkedItems = 0;
+ let allCheckedItems = 0;
+ let allCheckItems = 0;
+
+ for ( const checkItem of checkItems )
+ {
+ if ( checkItem.checked )
+ {
+ checkedItems++;
+ }
+ }
+
+ list.checkItemsChecked = checkedItems;
+
+ for ( const item of this.card.checklists )
+ {
+ allCheckItems += item.checkItems.length;
+ allCheckedItems += item.checkItemsChecked;
+ }
+
+ this.card.checkItems = allCheckItems;
+ this.card.checkItemsChecked = allCheckedItems;
+
+ this.updateCard();
+ }
+
+ /**
+ * Remove Checklist Item
+ * @param checkItem
+ * @param checklist
+ */
+ removeChecklistItem(checkItem, checklist)
+ {
+ checklist.checkItems.splice(checklist.checkItems.indexOf(checkItem), 1);
+
+ this.updateCheckedCount(checklist);
+
+ this.updateCard();
+ }
+
+ /**
+ * Add Check Item
+ * @param {NgForm} form
+ * @param checkList
+ */
+ addCheckItem(form: NgForm, checkList)
+ {
+ const checkItemVal = form.value.checkItem;
+
+ if ( !checkItemVal || checkItemVal === '' )
+ {
+ return;
+ }
+
+ const newCheckItem = {
+ 'name' : checkItemVal,
+ 'checked': false
+ };
+
+ checkList.checkItems.push(newCheckItem);
+
+ this.updateCheckedCount(checkList);
+
+ form.setValue({checkItem: ''});
+
+ this.updateCard();
+ }
+
+ /**
+ * Add Checklist
+ * @param {NgForm} form
+ */
+ addChecklist(form: NgForm)
+ {
+ this.card.checklists.push({
+ id : FuseUtils.generateGUID(),
+ name : form.value.checklistTitle,
+ checkItemsChecked: 0,
+ checkItems : []
+ });
+
+ form.setValue({checklistTitle: ''});
+ form.resetForm();
+ this.checklistMenu.closeMenu();
+ this.updateCard();
+ }
+
+ /**
+ * On Checklist Menu Open
+ */
+ onChecklistMenuOpen()
+ {
+ setTimeout(() => {
+ this.newCheckListTitleField._mdInputChild.focus();
+ });
+ }
+
+ /**
+ * Add New Comment
+ * @param {NgForm} form
+ */
+ addNewComment(form: NgForm)
+ {
+ const newCommentText = form.value.newComment;
+
+ const newComment = {
+ idMember: '36027j1930450d8bf7b10158',
+ message : newCommentText,
+ time : 'now'
+ };
+
+ this.card.comments.unshift(newComment);
+
+ form.setValue({newComment: ''});
+
+ this.updateCard();
+ }
+
+ /**
+ * Remove Card
+ */
+ removeCard()
+ {
+ this.dialogRef.close();
+ this.scrumboardService.removeCard(this.card.id, this.list.id);
+ }
+
+ /**
+ * Update Card
+ */
+ updateCard()
+ {
+ this.scrumboardService.updateCard(this.card);
+ }
+
+ ngOnDestroy()
+ {
+ this.onBoardChanged.unsubscribe();
+ }
+}
diff --git a/src/app/main/content/apps/scrumboard/board/dialogs/card/label-selector/label-selector.component.html b/src/app/main/content/apps/scrumboard/board/dialogs/card/label-selector/label-selector.component.html
new file mode 100644
index 00000000..dd9cb0d3
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/dialogs/card/label-selector/label-selector.component.html
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+ -1"
+ (change)="toggleInArray(label.id, card.idLabels);cardLabelsChanged()">
+ {{label.name}}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/app/main/content/apps/scrumboard/board/dialogs/card/label-selector/label-selector.component.scss b/src/app/main/content/apps/scrumboard/board/dialogs/card/label-selector/label-selector.component.scss
new file mode 100644
index 00000000..ff96a72e
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/dialogs/card/label-selector/label-selector.component.scss
@@ -0,0 +1,37 @@
+.scrumboard-labels-menu {
+
+ .mat-menu-content {
+ padding-bottom: 0;
+
+ .mat-checkbox-layout,
+ .mat-checkbox-label {
+ display: flex;
+ flex: 1;
+ }
+
+ .views {
+ display: flex;
+ flex-direction: column;
+ position: relative;
+ overflow: hidden;
+ width: 240px;
+ min-width: 240px;
+ max-width: 240px;
+ min-height: 240px;
+
+ .view {
+ position: absolute;
+ width: 240px;
+ height: 100%;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ top: 0;
+
+ > .header {
+ border-bottom: 1px solid rgba(0, 0, 0, 0.1);
+ }
+ }
+ }
+ }
+}
diff --git a/src/app/main/content/apps/scrumboard/board/dialogs/card/label-selector/label-selector.component.ts b/src/app/main/content/apps/scrumboard/board/dialogs/card/label-selector/label-selector.component.ts
new file mode 100644
index 00000000..9eda6022
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/dialogs/card/label-selector/label-selector.component.ts
@@ -0,0 +1,70 @@
+import { Component, EventEmitter, Input, OnDestroy, OnInit, Output, ViewEncapsulation } from '@angular/core';
+import { Subscription } from 'rxjs/Subscription';
+import { ScrumboardService } from '../../../../scrumboard.service';
+import { FuseUtils } from '../../../../../../../../core/fuseUtils';
+import { Animations } from '../../../../../../../../core/animations';
+
+@Component({
+ selector : 'fuse-scrumboard-label-selector',
+ templateUrl : './label-selector.component.html',
+ styleUrls : ['./label-selector.component.scss'],
+ encapsulation: ViewEncapsulation.None,
+ animations : [Animations.slideInLeft, Animations.slideInRight]
+})
+
+export class FuseScrumboardLabelSelectorComponent implements OnInit, OnDestroy
+{
+ board: any;
+ @Input('card') card: any;
+ @Output() onCardLabelsChange = new EventEmitter();
+
+ labelsMenuView = 'labels';
+ selectedLabel: any;
+ newLabel = {
+ 'id' : '',
+ 'name' : '',
+ 'color': 'md-blue-400-bg'
+ };
+ toggleInArray = FuseUtils.toggleInArray;
+
+ onBoardChanged: Subscription;
+
+ constructor(
+ private scrumboardService: ScrumboardService
+ )
+ {
+ }
+
+ ngOnInit()
+ {
+ this.onBoardChanged =
+ this.scrumboardService.onBoardChanged
+ .subscribe(board => {
+ this.board = board;
+ });
+ }
+
+ cardLabelsChanged()
+ {
+ this.onCardLabelsChange.next();
+ }
+
+ onLabelChange()
+ {
+ this.scrumboardService.updateBoard();
+ }
+
+ addNewLabel()
+ {
+ this.newLabel.id = FuseUtils.generateGUID();
+ this.board.labels.push(Object.assign({}, this.newLabel));
+ this.newLabel.name = '';
+ this.labelsMenuView = 'labels';
+ }
+
+ ngOnDestroy()
+ {
+ this.onBoardChanged.unsubscribe();
+ }
+
+}
diff --git a/src/app/main/content/apps/scrumboard/board/edit-board-name/edit-board-name.component.html b/src/app/main/content/apps/scrumboard/board/edit-board-name/edit-board-name.component.html
new file mode 100644
index 00000000..5a743fe3
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/edit-board-name/edit-board-name.component.html
@@ -0,0 +1,21 @@
+
+ {{board.name}}
+
+
+
+
+
diff --git a/src/app/main/content/apps/scrumboard/board/edit-board-name/edit-board-name.component.scss b/src/app/main/content/apps/scrumboard/board/edit-board-name/edit-board-name.component.scss
new file mode 100644
index 00000000..36f8f043
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/edit-board-name/edit-board-name.component.scss
@@ -0,0 +1,8 @@
+:host {
+ .board-name {
+ text-overflow: ellipsis;
+ overflow: hidden;
+ font-size: 15px;
+ font-weight: 500;
+ }
+}
diff --git a/src/app/main/content/apps/scrumboard/board/edit-board-name/edit-board-name.component.ts b/src/app/main/content/apps/scrumboard/board/edit-board-name/edit-board-name.component.ts
new file mode 100644
index 00000000..ddcbf583
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/edit-board-name/edit-board-name.component.ts
@@ -0,0 +1,61 @@
+import { Component, EventEmitter, Input, OnInit, Output, ViewChildren } from '@angular/core';
+import { FormBuilder, FormGroup } from '@angular/forms';
+
+@Component({
+ selector : 'fuse-scrumboard-edit-board-name',
+ templateUrl: './edit-board-name.component.html',
+ styleUrls : ['./edit-board-name.component.scss']
+})
+export class FuseScrumboardEditBoardNameComponent implements OnInit
+{
+ formActive = false;
+ form: FormGroup;
+ @Input() board;
+ @Output() onNameChanged = new EventEmitter();
+ @ViewChildren('nameInput') nameInputField;
+
+ constructor(
+ private formBuilder: FormBuilder
+ )
+ {
+ }
+
+ ngOnInit()
+ {
+
+ }
+
+ openForm()
+ {
+ this.form = this.formBuilder.group({
+ name: [this.board.name]
+ });
+ this.formActive = true;
+ this.focusNameField();
+ }
+
+ closeForm()
+ {
+ this.formActive = false;
+ }
+
+ focusNameField()
+ {
+ setTimeout(() => {
+ this.nameInputField.first.nativeElement.focus();
+ });
+ }
+
+ onFormSubmit()
+ {
+ if ( this.form.valid )
+ {
+ this.board.name = this.form.getRawValue().name;
+ this.board.uri = encodeURIComponent(this.board.name).replace(/%20/g, '-').toLowerCase();
+
+ this.onNameChanged.next(this.board.name);
+ this.formActive = false;
+ }
+ }
+
+}
diff --git a/src/app/main/content/apps/scrumboard/board/list/add-card/add-card.component.html b/src/app/main/content/apps/scrumboard/board/list/add-card/add-card.component.html
new file mode 100644
index 00000000..74a65988
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/list/add-card/add-card.component.html
@@ -0,0 +1,30 @@
+
+
+
diff --git a/src/app/main/content/apps/scrumboard/board/list/add-card/add-card.component.scss b/src/app/main/content/apps/scrumboard/board/list/add-card/add-card.component.scss
new file mode 100644
index 00000000..80fd08b3
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/list/add-card/add-card.component.scss
@@ -0,0 +1,39 @@
+:host {
+ .add-card-button {
+ position: relative;
+ height: 48px;
+ min-height: 48px;
+ padding: 0 16px;
+ text-align: left;
+ text-transform: none;
+ font-weight: 500;
+ font-size: 14px;
+ background-color: #DCDFE2;
+ cursor: pointer;
+ border-radius: 2px;
+
+ md-icon {
+ margin-right: 8px;
+ color: rgba(0, 0, 0, 0.6);
+ }
+ }
+
+ .add-card-form-wrapper {
+ background-color: #DCDFE2;
+
+ .add-card-form {
+ z-index: 999;
+ background: white;
+ display: block;
+ position: relative;
+ padding: 8px;
+ border-top: 1px solid rgba(0, 0, 0, 0.12);
+
+ md-input-container {
+ width: 100%;
+ margin: 0;
+ padding: 12px 8px;
+ }
+ }
+ }
+}
diff --git a/src/app/main/content/apps/scrumboard/board/list/add-card/add-card.component.ts b/src/app/main/content/apps/scrumboard/board/list/add-card/add-card.component.ts
new file mode 100644
index 00000000..977f1fd3
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/list/add-card/add-card.component.ts
@@ -0,0 +1,57 @@
+import { Component, ContentChildren, EventEmitter, Input, OnInit, Output, ViewChildren } from '@angular/core';
+import { FormBuilder, FormGroup } from '@angular/forms';
+
+@Component({
+ selector : 'fuse-scrumboard-board-add-card',
+ templateUrl: './add-card.component.html',
+ styleUrls : ['./add-card.component.scss']
+})
+export class FuseScrumboardBoardAddCardComponent implements OnInit
+{
+ formActive = false;
+ form: FormGroup;
+ @Output() onCardAdd = new EventEmitter();
+ @ViewChildren('nameInput') nameInputField;
+
+ constructor(
+ private formBuilder: FormBuilder
+ )
+ {
+ }
+
+ ngOnInit()
+ {
+ }
+
+ openForm()
+ {
+ this.form = this.formBuilder.group({
+ name: ''
+ });
+ this.formActive = true;
+ this.focusNameField();
+ }
+
+ closeForm()
+ {
+ this.formActive = false;
+ }
+
+ focusNameField()
+ {
+ setTimeout(() => {
+ this.nameInputField.first._mdInputChild.focus();
+ });
+ }
+
+ onFormSubmit()
+ {
+ if ( this.form.valid )
+ {
+ const cardName = this.form.getRawValue().name;
+ this.onCardAdd.next(cardName);
+ this.formActive = false;
+ }
+ }
+}
+
diff --git a/src/app/main/content/apps/scrumboard/board/list/card/card.component.html b/src/app/main/content/apps/scrumboard/board/list/card/card.component.html
new file mode 100644
index 00000000..fd772ed0
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/list/card/card.component.html
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
0"
+ class="list-card-labels"
+ fxLayout="row" layout-wrap>
+
+
+
+
+
+
+
+
+
{{card.name}}
+
+
+
+
+
+
+ access_time
+ {{card.due | date:'mediumDate'}}
+
+
+
+
+
+
+ check_circle
+ {{card.checkItemsChecked}}
+ /
+ {{card.checkItems}}
+
+
+
+
+
+
+
0"
+ class="list-card-members"
+ fxLayout="row">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/app/main/content/apps/scrumboard/board/list/card/card.component.scss b/src/app/main/content/apps/scrumboard/board/list/card/card.component.scss
new file mode 100644
index 00000000..79d56b2e
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/list/card/card.component.scss
@@ -0,0 +1,114 @@
+@import "src/app/core/scss/fuse";
+
+:host {
+ position: relative;
+ display: block;
+ width: 100%;
+ margin: 16px 0;
+ background-color: white;
+ color: #000;
+ border-radius: 2px;
+ transition: box-shadow 150ms ease;
+ cursor: pointer;
+
+ &.ui-sortable-helper {
+ box-shadow: 0px 5px 5px -3px rgba(0, 0, 0, 0.2), 0px 8px 10px 1px rgba(0, 0, 0, 0.14), 0px 3px 14px 2px rgba(0, 0, 0, 0.12);
+ }
+
+ .list-card-sort-handle {
+ display: none;
+ position: absolute;
+ top: 0;
+ right: 0;
+ padding: 4px;
+ background: rgba(255, 255, 255, 0.8);
+ }
+
+ .list-card-cover {
+ }
+
+ .list-card-details {
+ padding: 16px 16px 0 16px;
+
+ .list-card-labels {
+ margin-bottom: 6px;
+
+ .list-card-label {
+ width: 32px;
+ height: 6px;
+ border-radius: 6px;
+ margin: 0 6px 6px 0;
+ }
+ }
+
+ .list-card-name {
+ font-size: 14px;
+ font-weight: 500;
+ margin-bottom: 12px;
+ }
+
+ .list-card-badges {
+ margin-bottom: 12px;
+
+ .badge {
+ margin-right: 8px;
+ padding: 4px 8px;
+ border-radius: 2px;
+ background-color: rgba(0, 0, 0, 0.4);
+ color: #FFFFFF;
+
+ md-icon {
+ margin-right: 4px;
+ }
+
+ &.due-date {
+ background-color: mat-color(mat-palette($mat-green));;
+
+ &.overdue {
+ background-color: mat-color(mat-palette($mat-red));
+ }
+ }
+
+ &.check-items {
+
+ &.completed {
+ background-color: mat-color(mat-palette($mat-green));
+ }
+ }
+ }
+ }
+
+ .list-card-members {
+ margin-bottom: 12px;
+
+ .list-card-member {
+ margin-right: 8px;
+
+ .list-card-member-avatar {
+ border-radius: 50%;
+ width: 32px;
+ height: 32px;
+ }
+ }
+ }
+ }
+
+ .list-card-footer {
+ border-top: 1px solid rgba(0, 0, 0, 0.12);
+ padding: 0 16px;
+
+ .list-card-footer-item {
+ height: 48px;
+ margin-right: 12px;
+ color: rgba(0, 0, 0, 0.66);
+
+ .value {
+ padding-left: 8px;
+ }
+
+ &:last-of-type {
+ margin-right: 0;
+ }
+ }
+ }
+}
diff --git a/src/app/main/content/apps/scrumboard/board/list/card/card.component.ts b/src/app/main/content/apps/scrumboard/board/list/card/card.component.ts
new file mode 100644
index 00000000..8ec3ab68
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/list/card/card.component.ts
@@ -0,0 +1,43 @@
+import { Component, Input, OnInit } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+import { ScrumboardService } from '../../../scrumboard.service';
+import * as moment from 'moment';
+
+@Component({
+ selector : 'fuse-scrumboard-board-card',
+ templateUrl: './card.component.html',
+ styleUrls : ['./card.component.scss']
+})
+export class FuseScrumboardBoardCardComponent implements OnInit
+{
+ @Input() cardId;
+ card: any;
+ board: any;
+
+ constructor(
+ private route: ActivatedRoute,
+ private scrumboardService: ScrumboardService
+ )
+ {
+ }
+
+ ngOnInit()
+ {
+ this.board = this.route.snapshot.data.board;
+ this.card = this.board.cards.filter((card) => {
+ return this.cardId === card.id;
+ })[0];
+ }
+
+ /**
+ * Is the card overdue?
+ *
+ * @param cardDate
+ * @returns {boolean}
+ */
+ isOverdue(cardDate)
+ {
+ return moment() > moment(new Date(cardDate));
+ }
+
+}
diff --git a/src/app/main/content/apps/scrumboard/board/list/edit-list-name/edit-list-name.component.html b/src/app/main/content/apps/scrumboard/board/list/edit-list-name/edit-list-name.component.html
new file mode 100644
index 00000000..c8218cad
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/list/edit-list-name/edit-list-name.component.html
@@ -0,0 +1,17 @@
+
+
+
diff --git a/src/app/main/content/apps/scrumboard/board/list/edit-list-name/edit-list-name.component.scss b/src/app/main/content/apps/scrumboard/board/list/edit-list-name/edit-list-name.component.scss
new file mode 100644
index 00000000..aee46891
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/list/edit-list-name/edit-list-name.component.scss
@@ -0,0 +1,9 @@
+:host {
+ .list-header-name {
+ text-overflow: ellipsis;
+ overflow: hidden;
+ font-size: 15px;
+ font-weight: 500;
+ cursor: pointer;
+ }
+}
diff --git a/src/app/main/content/apps/scrumboard/board/list/edit-list-name/edit-list-name.component.ts b/src/app/main/content/apps/scrumboard/board/list/edit-list-name/edit-list-name.component.ts
new file mode 100644
index 00000000..bb2cc7b2
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/list/edit-list-name/edit-list-name.component.ts
@@ -0,0 +1,59 @@
+import { Component, EventEmitter, Input, OnInit, Output, ViewChildren } from '@angular/core';
+import { FormBuilder, FormGroup } from '@angular/forms';
+
+@Component({
+ selector : 'fuse-scrumboard-board-edit-list-name',
+ templateUrl: './edit-list-name.component.html',
+ styleUrls : ['./edit-list-name.component.scss']
+})
+export class FuseScrumboardBoardEditListNameComponent implements OnInit
+{
+ formActive = false;
+ form: FormGroup;
+ @Input() list;
+ @Output() onNameChanged = new EventEmitter();
+ @ViewChildren('nameInput') nameInputField;
+
+ constructor(
+ private formBuilder: FormBuilder
+ )
+ {
+ }
+
+ ngOnInit()
+ {
+
+ }
+
+ openForm()
+ {
+ this.form = this.formBuilder.group({
+ name: [this.list.name]
+ });
+ this.formActive = true;
+ this.focusNameField();
+ }
+
+ closeForm()
+ {
+ this.formActive = false;
+ }
+
+ focusNameField()
+ {
+ setTimeout(() => {
+ this.nameInputField.first.nativeElement.focus();
+ });
+ }
+
+ onFormSubmit()
+ {
+ if ( this.form.valid )
+ {
+ this.list.name = this.form.getRawValue().name;
+ this.onNameChanged.next(this.list.name);
+ this.formActive = false;
+ }
+ }
+
+}
diff --git a/src/app/main/content/apps/scrumboard/board/list/list.component.html b/src/app/main/content/apps/scrumboard/board/list/list.component.html
new file mode 100644
index 00000000..ae544bd8
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/list/list.component.html
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/app/main/content/apps/scrumboard/board/list/list.component.scss b/src/app/main/content/apps/scrumboard/board/list/list.component.scss
new file mode 100644
index 00000000..75cc7d82
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/list/list.component.scss
@@ -0,0 +1,57 @@
+:host {
+ width: 344px;
+ min-width: 344px;
+ max-width: 344px;
+ padding-right: 24px;
+ height: 100%;
+
+ &.ui-sortable-helper .list {
+ box-shadow: 0px 5px 5px -3px rgba(0, 0, 0, 0.2), 0px 8px 10px 1px rgba(0, 0, 0, 0.14), 0px 3px 14px 2px rgba(0, 0, 0, 0.12);
+ }
+
+ .list {
+ max-height: 100%;
+ background-color: #EEF0F2;
+ color: #000;
+ border-radius: 2px;
+ transition: box-shadow 150ms ease;
+
+ .list-header {
+ height: 64px;
+ min-height: 64px;
+ padding: 0 0 0 16px;
+ border-bottom: 1px solid rgba(0, 0, 0, 0.12);
+
+
+ }
+
+ .list-content {
+ position: relative;
+ overflow: hidden;
+ overflow-y: auto;
+ min-height: 0;
+
+ .list-cards {
+ position: relative;
+ min-height: 32px;
+ padding: 0 16px;
+
+ .card-sortable-placeholder {
+ background: rgba(0, 0, 0, 0.06);
+ }
+
+ > div {
+ transition: none !important;
+ }
+ }
+ }
+
+ .list-footer {
+ display: flex;
+ flex-direction: column;
+ flex: 1 0 auto;
+ min-height: 48px;
+ }
+
+ }
+}
diff --git a/src/app/main/content/apps/scrumboard/board/list/list.component.ts b/src/app/main/content/apps/scrumboard/board/list/list.component.ts
new file mode 100644
index 00000000..e471340a
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/list/list.component.ts
@@ -0,0 +1,104 @@
+import { Component, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
+import { FuseUtils } from '../../../../../../core/fuseUtils';
+import { ScrumboardService } from 'app/main/content/apps/scrumboard/scrumboard.service';
+import { ActivatedRoute } from '@angular/router';
+import { Subscription } from 'rxjs/Subscription';
+import { PerfectScrollbarDirective } from 'ngx-perfect-scrollbar';
+import { MdDialog } from '@angular/material';
+import { FuseScrumboardCardDialogComponent } from '../dialogs/card/card.component';
+
+@Component({
+ selector : 'fuse-scrumboard-board-list',
+ templateUrl: './list.component.html',
+ styleUrls : ['./list.component.scss']
+})
+export class FuseScrumboardBoardListComponent implements OnInit, OnDestroy
+{
+ board: any;
+ dialogRef: any;
+
+ @Input() list;
+ @ViewChild(PerfectScrollbarDirective) listScroll: PerfectScrollbarDirective;
+
+ onBoardChanged: Subscription;
+
+ constructor(
+ private route: ActivatedRoute,
+ private scrumboardService: ScrumboardService,
+ public dialog: MdDialog
+ )
+ {
+ }
+
+ ngOnInit()
+ {
+ this.onBoardChanged =
+ this.scrumboardService.onBoardChanged
+ .subscribe(board => {
+ this.board = board;
+ });
+
+ }
+
+ onListNameChanged(newListName)
+ {
+ this.list.name = newListName;
+ }
+
+ onCardAdd(newCardName)
+ {
+ if ( newCardName === '' )
+ {
+ return;
+ }
+
+ const newCard = {
+ id : FuseUtils.generateGUID(),
+ name : newCardName,
+ description : '',
+ idAttachmentCover: '',
+ idMembers : [],
+ idLabels : [],
+ attachments : [],
+ subscribed : false,
+ checklists : [],
+ checkItems : 0,
+ checkItemsChecked: 0,
+ comments : [],
+ activities : [],
+ due : null
+ };
+
+ this.scrumboardService.addCard(this.list.id, newCard);
+
+ setTimeout(() => {
+ this.listScroll.scrollToBottom(0, 400);
+ });
+
+ }
+
+ removeList(listId)
+ {
+ this.scrumboardService.removeList(listId);
+ }
+
+ openCardDialog(cardId)
+ {
+ this.dialogRef = this.dialog.open(FuseScrumboardCardDialogComponent, {
+ panelClass: 'scrumboard-card-dialog',
+ data : {
+ cardId: cardId,
+ listId: this.list.id
+ }
+ });
+ this.dialogRef.afterClosed()
+ .subscribe(response => {
+
+ });
+ }
+
+ ngOnDestroy()
+ {
+ this.onBoardChanged.unsubscribe();
+ }
+}
diff --git a/src/app/main/content/apps/scrumboard/board/sidenavs/settings/settings.component.html b/src/app/main/content/apps/scrumboard/board/sidenavs/settings/settings.component.html
new file mode 100644
index 00000000..47485e4b
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/sidenavs/settings/settings.component.html
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
format_color_fill
+
Board Color
+
+
+
+
+
+
photo
+
Card Cover Images
+
check
+
+
+
+
+
+
remove_red_eye
+
Subscribe
+
check
+
+
+
+
+
+
content_copy
+
Copy Board
+
+
+
+
+
+
delete
+
Delete Board
+
+
+
+
+
+
+
diff --git a/src/app/main/content/apps/scrumboard/board/sidenavs/settings/settings.component.scss b/src/app/main/content/apps/scrumboard/board/sidenavs/settings/settings.component.scss
new file mode 100644
index 00000000..678b3c81
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/sidenavs/settings/settings.component.scss
@@ -0,0 +1,11 @@
+:host {
+ display: flex;
+ flex-direction: column;
+ flex: 1 0 auto;
+ height: 100%;
+
+ > .header {
+ flex: 0 1 auto;
+ border-bottom: 1px solid rgba(0, 0, 0, 0.12);
+ }
+}
diff --git a/src/app/main/content/apps/scrumboard/board/sidenavs/settings/settings.component.ts b/src/app/main/content/apps/scrumboard/board/sidenavs/settings/settings.component.ts
new file mode 100644
index 00000000..0e539149
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/board/sidenavs/settings/settings.component.ts
@@ -0,0 +1,49 @@
+import { Component, OnInit } from '@angular/core';
+import { Subscription } from 'rxjs/Subscription';
+import { ScrumboardService } from '../../../scrumboard.service';
+
+@Component({
+ selector : 'fuse-scrumboard-board-settings',
+ templateUrl: './settings.component.html',
+ styleUrls : ['./settings.component.scss']
+})
+export class FuseScrumboardBoardSettingsSidenavComponent implements OnInit
+{
+ board: any;
+ onBoardChanged: Subscription;
+
+ constructor(
+ private scrumboardService: ScrumboardService
+ )
+ {
+
+ }
+
+ ngOnInit()
+ {
+ this.onBoardChanged =
+ this.scrumboardService.onBoardChanged
+ .subscribe(board => {
+ this.board = board;
+ });
+ }
+
+ toggleCardCover()
+ {
+ this.board.settings.cardCoverImages = !this.board.settings.cardCoverImages;
+ this.updateBoard();
+ }
+
+ toggleSubcription()
+ {
+ this.board.settings.subscribed = !this.board.settings.subscribed;
+ this.updateBoard();
+ }
+
+ updateBoard()
+ {
+ this.scrumboardService.onBoardChanged.next(this.board);
+ this.scrumboardService.updateBoard();
+ }
+
+}
diff --git a/src/app/main/content/apps/scrumboard/scrumboard.component.html b/src/app/main/content/apps/scrumboard/scrumboard.component.html
new file mode 100644
index 00000000..f617a2d9
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/scrumboard.component.html
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
Scrumboard App
+
+
+
+
+
+
+
assessment
+
{{board.name}}
+
+
+
+
+
+
add_circle
+
Add new board
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/app/main/content/apps/scrumboard/scrumboard.component.scss b/src/app/main/content/apps/scrumboard/scrumboard.component.scss
new file mode 100644
index 00000000..13eb32d4
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/scrumboard.component.scss
@@ -0,0 +1,187 @@
+@import "src/app/core/scss/fuse";
+
+:host {
+ min-height: 100%;
+
+ #board-selector {
+ margin-top: 88px;
+
+ .board-list {
+ padding: 32px 0;
+
+ .board-list-item {
+ min-width: 210px;
+ width: 210px;
+ padding: 24px 0;
+ margin: 16px;
+ border-radius: 2px;
+ background: rgba(0, 0, 0, 0.12);
+ cursor: pointer;
+
+ &:hover {
+ @include mat-elevation(4);
+ }
+
+ .board-name {
+ padding-top: 16px;
+ font-weight: 500;
+ }
+ }
+ }
+ }
+}
+
+#scrumboard {
+ height: 100%;
+
+ > .header {
+ position: relative;
+ height: 96px;
+ min-height: 96px;
+ max-height: 96px;
+ background-image: none;
+ z-index: 49;
+
+ .header-content {
+
+ .header-boards-button {
+ margin: 0;
+ }
+
+ .header-board-name {
+ font-size: 16px;
+
+ .board-subscribe {
+ margin-right: 8px;
+ }
+
+ .editable-buttons {
+
+ md-icon {
+ color: #FFFFFF !important;
+ }
+ }
+ }
+
+ .right-side {
+
+ > .md-button:last-child {
+ margin-right: 0;
+ }
+ }
+
+ }
+ }
+
+ #board-selector {
+ position: absolute;
+ top: 96px;
+ right: 0;
+ left: 0;
+ height: 192px;
+ z-index: 48;
+ padding: 24px;
+ opacity: 1;
+
+ .board-list-item {
+ width: 128px;
+ height: 192px;
+ padding: 16px;
+ cursor: pointer;
+ position: relative;
+
+ .board-name {
+ text-align: center;
+ padding: 16px 0;
+ }
+
+ .selected-icon {
+ position: absolute;
+ top: 0;
+ left: 50%;
+ width: 32px;
+ height: 32px;
+ margin-left: -16px;
+ border-radius: 50%;
+ text-align: center;
+ color: white;
+
+ i {
+ line-height: 32px !important;
+ }
+ }
+
+ &.add-new-board {
+ opacity: 0.6;
+ }
+ }
+ }
+
+ .content {
+ padding: 0;
+ background: transparent;
+ }
+
+ .editable-click {
+ cursor: pointer;
+ text-decoration: none;
+ color: inherit;
+ border-bottom: none;
+ }
+
+ .editable-wrap {
+ display: block;
+ position: relative;
+
+ .editable-controls {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ width: 100%;
+
+ .editable-input {
+ width: inherit;
+ background-color: white;
+ padding: 8px;
+ border: 1px solid rgba(0, 0, 0, 0.12);
+ }
+
+ .editable-buttons {
+ display: inherit;
+
+ .md-button {
+ margin: 0;
+
+ &:first-of-type {
+ padding-right: 0;
+ }
+
+ .icon-cancel {
+ color: rgba(0, 0, 0, 0.32);
+ }
+ }
+ }
+ }
+ }
+
+ .board-selector-backdrop {
+ z-index: 47;
+ }
+}
+
+// RESPONSIVE
+@include media-breakpoint(xs) {
+ #scrumboard {
+
+ .header {
+ height: 120px;
+ max-height: 120px;
+ min-height: 120px;
+
+ }
+
+ #board-selector {
+ top: 120px;
+ }
+ }
+}
diff --git a/src/app/main/content/apps/scrumboard/scrumboard.component.ts b/src/app/main/content/apps/scrumboard/scrumboard.component.ts
new file mode 100644
index 00000000..c3c51247
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/scrumboard.component.ts
@@ -0,0 +1,103 @@
+import { Component, OnDestroy, OnInit } from '@angular/core';
+import { ScrumboardService } from './scrumboard.service';
+import { Subscription } from 'rxjs/Subscription';
+import { FuseUtils } from '../../../../core/fuseUtils';
+import { Router } from '@angular/router';
+
+@Component({
+ selector : 'fuse-scrumboard',
+ templateUrl: './scrumboard.component.html',
+ styleUrls : ['./scrumboard.component.scss']
+})
+export class FuseScrumboardComponent implements OnInit, OnDestroy
+{
+ boards: any[];
+ onBoardsChanged: Subscription;
+
+ constructor(
+ private router: Router,
+ private scrumboardService: ScrumboardService
+ )
+ {
+
+ }
+
+ ngOnInit()
+ {
+ this.onBoardsChanged =
+ this.scrumboardService.onBoardsChanged
+ .subscribe(boards => {
+ this.boards = boards;
+ });
+
+ }
+
+ newBoard()
+ {
+ const newBoard = {
+ name : 'Untitled Board',
+ uri : 'untitled-board',
+ id : FuseUtils.generateGUID(),
+ settings: {
+ color : '',
+ subscribed : true,
+ cardCoverImages: true
+ },
+ lists : [],
+ cards : [],
+ members : [
+ {
+ id : '56027c1930450d8bf7b10758',
+ name : 'Alice Freeman',
+ avatar: 'assets/images/avatars/alice.jpg'
+ },
+ {
+ id : '26027s1930450d8bf7b10828',
+ name : 'Danielle Obrien',
+ avatar: 'assets/images/avatars/danielle.jpg'
+ },
+ {
+ id : '76027g1930450d8bf7b10958',
+ name : 'James Lewis',
+ avatar: 'assets/images/avatars/james.jpg'
+ },
+ {
+ id : '36027j1930450d8bf7b10158',
+ name : 'Vincent Munoz',
+ avatar: 'assets/images/avatars/vincent.jpg'
+ }
+ ],
+ labels : [
+ {
+ id : '26022e4129ad3a5sc28b36cd',
+ name : 'High Priority',
+ color: 'red'
+ },
+ {
+ id : '56027e4119ad3a5dc28b36cd',
+ name : 'Design',
+ color: 'orange'
+ },
+ {
+ id : '5640635e19ad3a5dc21416b2',
+ name : 'App',
+ color: 'blue'
+ },
+ {
+ id : '6540635g19ad3s5dc31412b2',
+ name : 'Feature',
+ color: 'green'
+ }
+ ]
+ };
+
+ this.scrumboardService.createNewBoard(newBoard).then(() => {
+ this.router.navigate(['/apps/scrumboard/boards/' + newBoard.id + '/' + newBoard.uri]);
+ });
+ }
+
+ ngOnDestroy()
+ {
+ this.onBoardsChanged.unsubscribe();
+ }
+}
diff --git a/src/app/main/content/apps/scrumboard/scrumboard.module.ts b/src/app/main/content/apps/scrumboard/scrumboard.module.ts
new file mode 100644
index 00000000..1ea08217
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/scrumboard.module.ts
@@ -0,0 +1,64 @@
+import { NgModule } from '@angular/core';
+import { SharedModule } from '../../../../core/modules/shared.module';
+import { RouterModule, Routes } from '@angular/router';
+import { FuseScrumboardComponent } from './scrumboard.component';
+import { BoardResolve, ScrumboardService } from './scrumboard.service';
+import { FuseScrumboardBoardComponent } from './board/board.component';
+import { FuseScrumboardBoardListComponent } from './board/list/list.component';
+import { FuseScrumboardBoardCardComponent } from './board/list/card/card.component';
+import { FuseScrumboardBoardEditListNameComponent } from './board/list/edit-list-name/edit-list-name.component';
+import { FuseScrumboardBoardAddCardComponent } from './board/list/add-card/add-card.component';
+import { FuseScrumboardBoardAddListComponent } from './board/add-list/add-list.component';
+import { FuseScrumboardCardDialogComponent } from './board/dialogs/card/card.component';
+import { FuseScrumboardLabelSelectorComponent } from './board/dialogs/card/label-selector/label-selector.component';
+import { FuseScrumboardEditBoardNameComponent } from './board/edit-board-name/edit-board-name.component';
+import { FuseScrumboardBoardSettingsSidenavComponent } from './board/sidenavs/settings/settings.component';
+
+const routes: Routes = [
+ {
+ path : 'boards',
+ component: FuseScrumboardComponent,
+ resolve : {
+ scrumboard: ScrumboardService
+ }
+ },
+ {
+ path : 'boards/:boardId/:boardUri',
+ component: FuseScrumboardBoardComponent,
+ resolve : {
+ board: BoardResolve
+ }
+ },
+ {
+ path : '**',
+ redirectTo: 'boards'
+ }
+];
+
+@NgModule({
+ declarations : [
+ FuseScrumboardComponent,
+ FuseScrumboardBoardComponent,
+ FuseScrumboardBoardListComponent,
+ FuseScrumboardBoardCardComponent,
+ FuseScrumboardBoardEditListNameComponent,
+ FuseScrumboardBoardAddCardComponent,
+ FuseScrumboardBoardAddListComponent,
+ FuseScrumboardCardDialogComponent,
+ FuseScrumboardLabelSelectorComponent,
+ FuseScrumboardEditBoardNameComponent,
+ FuseScrumboardBoardSettingsSidenavComponent
+ ],
+ imports : [
+ SharedModule,
+ RouterModule.forChild(routes)
+ ],
+ providers : [
+ ScrumboardService,
+ BoardResolve
+ ],
+ entryComponents: [FuseScrumboardCardDialogComponent]
+})
+export class FuseScrumboardModule
+{
+}
diff --git a/src/app/main/content/apps/scrumboard/scrumboard.service.ts b/src/app/main/content/apps/scrumboard/scrumboard.service.ts
new file mode 100644
index 00000000..f26c3e9e
--- /dev/null
+++ b/src/app/main/content/apps/scrumboard/scrumboard.service.ts
@@ -0,0 +1,174 @@
+import { Injectable } from '@angular/core';
+import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router';
+import { Observable } from 'rxjs/Observable';
+import { Http } from '@angular/http';
+import { BehaviorSubject } from 'rxjs/BehaviorSubject';
+
+@Injectable()
+export class ScrumboardService implements Resolve
+{
+ boards: any[];
+ routeParams: any;
+ board: any;
+
+ onBoardsChanged: BehaviorSubject = new BehaviorSubject([]);
+ onBoardChanged: BehaviorSubject = new BehaviorSubject([]);
+
+ constructor(private http: Http)
+ {
+ }
+
+ /**
+ * Resolve
+ * @param {ActivatedRouteSnapshot} route
+ * @param {RouterStateSnapshot} state
+ * @returns {Observable | Promise | any}
+ */
+ resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable | Promise | any
+ {
+ this.routeParams = route.params;
+
+ return new Promise((resolve, reject) => {
+ Promise.all([
+ this.getBoards()
+ ]).then(
+ () => {
+ resolve();
+ },
+ reject
+ );
+ });
+ }
+
+ getBoards(): Promise
+ {
+ return new Promise((resolve, reject) => {
+ this.http.get('api/scrumboard-boards')
+ .subscribe(response => {
+ this.boards = response.json().data;
+ this.onBoardsChanged.next(this.boards);
+ resolve(this.boards);
+ }, reject);
+ });
+ }
+
+ getBoard(boardId): Promise
+ {
+ return new Promise((resolve, reject) => {
+ this.http.get('api/scrumboard-boards/' + boardId)
+ .subscribe(response => {
+ this.board = response.json().data;
+ this.onBoardChanged.next(this.board);
+ resolve(this.board);
+ }, reject);
+ });
+ }
+
+ addCard(listId, newCard)
+ {
+ this.board.lists.map((list) => {
+ if ( list.id === listId )
+ {
+ return list.idCards.push(newCard.id);
+ }
+ });
+
+ this.board.cards.push(newCard);
+
+ return this.updateBoard();
+ }
+
+ addList(newList)
+ {
+
+ this.board.lists.push(newList);
+
+ return this.updateBoard();
+
+ }
+
+ removeList(listId)
+ {
+ const list = this.board.lists.find((_list) => {
+ return _list.id === listId;
+ });
+
+ for ( const cardId of list.idCards )
+ {
+ this.removeCard(cardId);
+ }
+
+ const index = this.board.lists.indexOf(list);
+
+ this.board.lists.splice(index, 1);
+
+ return this.updateBoard();
+ }
+
+ removeCard(cardId, listId?)
+ {
+
+ const card = this.board.cards.find((_card) => {
+ return _card.id === cardId;
+ });
+
+ if ( listId )
+ {
+ const list = this.board.lists.find((_list) => {
+ return listId === _list.id;
+ });
+ list.idCards.splice(list.idCards.indexOf(cardId), 1);
+ }
+
+ this.board.cards.splice(this.board.cards.indexOf(card), 1);
+
+ this.updateBoard();
+ }
+
+ updateBoard()
+ {
+ return new Promise((resolve, reject) => {
+ this.http.post('api/scrumboard-boards/' + this.board.id, this.board)
+ .subscribe(response => {
+ this.onBoardChanged.next(this.board);
+ resolve(this.board);
+ }, reject);
+ });
+ }
+
+ updateCard(newCard)
+ {
+ this.board.cards.map((_card) => {
+ if ( _card.id === newCard.id )
+ {
+ return newCard;
+ }
+ });
+
+ this.updateBoard();
+ }
+
+ createNewBoard(board)
+ {
+ return new Promise((resolve, reject) => {
+ this.http.post('api/scrumboard-boards/' + board.id, board)
+ .subscribe(response => {
+ resolve(board);
+ }, reject);
+ });
+ }
+}
+
+@Injectable()
+export class BoardResolve implements Resolve
+{
+
+ constructor(private scrumboardService: ScrumboardService)
+ {
+ }
+
+ resolve(route: ActivatedRouteSnapshot)
+ {
+ return this.scrumboardService.getBoard(route.paramMap.get('boardId'));
+ }
+}
diff --git a/src/app/navigation.model.ts b/src/app/navigation.model.ts
index 5aa081be..95191344 100644
--- a/src/app/navigation.model.ts
+++ b/src/app/navigation.model.ts
@@ -72,6 +72,12 @@ export class FuseNavigation
'fg' : '#FFFFFF'
}
},
+ {
+ 'title': 'Scrumboard',
+ 'type' : 'nav-item',
+ 'icon' : 'assessment',
+ 'url' : '/apps/scrumboard'
+ },
{
'title': 'PAGES',
'type' : 'subheader'