diff --git a/src/app/@core/core.module.ts b/src/app/@core/core.module.ts index 1135104..d31a5bd 100644 --- a/src/app/@core/core.module.ts +++ b/src/app/@core/core.module.ts @@ -10,7 +10,7 @@ import { LayoutService, PlayerService, SeoService, - StateService, + StateServiceForNB, } from './utils'; import { UserData } from './data/users'; import { ElectricityData } from './data/electricity'; @@ -142,7 +142,7 @@ export const NB_CORE_PROVIDERS = [ LayoutService, PlayerService, SeoService, - StateService, + StateServiceForNB, ]; @NgModule({ diff --git a/src/app/@core/utils/index.ts b/src/app/@core/utils/index.ts index 1b3f94d..d62b130 100644 --- a/src/app/@core/utils/index.ts +++ b/src/app/@core/utils/index.ts @@ -1,7 +1,7 @@ import { LayoutService } from './layout.service'; import { AnalyticsService } from './analytics.service'; import { PlayerService } from './player.service'; -import { StateService } from './state.service'; +import { StateServiceForNB } from './state.service'; import { SeoService } from './seo.service'; export { @@ -9,5 +9,5 @@ export { AnalyticsService, PlayerService, SeoService, - StateService, + StateServiceForNB, }; diff --git a/src/app/@core/utils/state.service.ts b/src/app/@core/utils/state.service.ts index 3f0847d..f4d17b3 100644 --- a/src/app/@core/utils/state.service.ts +++ b/src/app/@core/utils/state.service.ts @@ -1,11 +1,11 @@ import { Injectable, OnDestroy } from '@angular/core'; -import { of as observableOf, Observable, BehaviorSubject } from 'rxjs'; +import { of as observableOf, Observable, BehaviorSubject } from 'rxjs'; import { takeWhile } from 'rxjs/operators'; import { NbLayoutDirectionService, NbLayoutDirection } from '@nebular/theme'; @Injectable() -export class StateService implements OnDestroy { +export class StateServiceForNB implements OnDestroy { protected layouts: any = [ { @@ -58,7 +58,7 @@ export class StateService implements OnDestroy { } private updateSidebarIcons(direction: NbLayoutDirection) { - const [ startSidebar, endSidebar ] = this.sidebars; + const [startSidebar, endSidebar] = this.sidebars; const isLtr = direction === NbLayoutDirection.LTR; const startIconClass = isLtr ? 'nb-layout-sidebar-left' : 'nb-layout-sidebar-right'; const endIconClass = isLtr ? 'nb-layout-sidebar-right' : 'nb-layout-sidebar-left'; diff --git a/src/app/@theme/components/header/breakPoint.ts b/src/app/@theme/components/header/breakPoint.ts new file mode 100644 index 0000000..05693cb --- /dev/null +++ b/src/app/@theme/components/header/breakPoint.ts @@ -0,0 +1,34 @@ +export const DEFAULT_MEDIA_BREAKPOINTS = [ + { + name: 'xs', + width: 0, + }, + { + name: 'is', + width: 400, + }, + { + name: 'sm', + width: 576, + }, + { + name: 'md', + width: 768, + }, + { + name: 'lg', + width: 992, + }, + { + name: 'xl', + width: 1200, + }, + { + name: 'xxl', + width: 1400, + }, + { + name: 'xxxl', + width: 1600, + }, +]; \ No newline at end of file diff --git a/src/app/@theme/components/header/header.component.ts b/src/app/@theme/components/header/header.component.ts index c9091c7..9d61682 100644 --- a/src/app/@theme/components/header/header.component.ts +++ b/src/app/@theme/components/header/header.component.ts @@ -9,6 +9,7 @@ import { HeaderService } from '../../../services/header.service'; import { NbAuthService } from '@nebular/auth'; import { AuthService } from '../../../services/auth.service'; import { UserProfileAction } from '../../../entity/Auth'; +import { Router } from '@angular/router'; @Component({ selector: 'ngx-header', @@ -19,6 +20,7 @@ export class HeaderComponent implements OnInit, OnDestroy { header: string = ''; private destroy$: Subject = new Subject(); userPictureOnly: boolean = false; + isLessThanMd: boolean = false; themes = [ { @@ -68,7 +70,8 @@ export class HeaderComponent implements OnInit, OnDestroy { return null; } } - constructor(private sidebarService: NbSidebarService, + constructor( + private sidebarService: NbSidebarService, private menuService: NbMenuService, private themeService: NbThemeService, private userService: UserData, @@ -77,15 +80,12 @@ export class HeaderComponent implements OnInit, OnDestroy { private headerService: HeaderService, private oAuthService: NbAuthService, private authService: AuthService, + protected router: Router, ) { this.headerService.headerChange$.pipe(takeUntil(this.destroy$)).subscribe(result => { this.header = result; }); - this.menuService.onItemClick().pipe(takeUntil(this.destroy$)) - .subscribe(result => { - if (result.item.title == 'Log out') this.logout(); - }); } @@ -93,13 +93,18 @@ export class HeaderComponent implements OnInit, OnDestroy { ngOnInit() { this.currentTheme = this.themeService.currentTheme; - const { xl } = this.breakpointService.getBreakpointsMap(); + const { md, xl } = this.breakpointService.getBreakpointsMap(); this.themeService.onMediaQueryChange() .pipe( - map(([, currentBreakpoint]) => currentBreakpoint.width < xl), + map(([, currentBreakpoint]) => currentBreakpoint.width), takeUntil(this.destroy$), ) - .subscribe((isLessThanXl: boolean) => this.userPictureOnly = isLessThanXl); + .subscribe((screenWidth: number) => { + let isLessThanXl = screenWidth < xl; + this.isLessThanMd = screenWidth < md; + this.userPictureOnly = isLessThanXl + + }); this.themeService.onThemeChange() .pipe( @@ -108,6 +113,22 @@ export class HeaderComponent implements OnInit, OnDestroy { ) .subscribe(themeName => this.currentTheme = themeName); + this.menuService.onItemClick().subscribe(result => { + if (this.isLessThanMd && result.tag == 'NavMenu' && result.item.link) { + this.toggleSidebar(); + } else if (result.tag == 'UserProfileMenu') { + switch (result.item.data as UserProfileAction) { + case UserProfileAction.None: break; + case UserProfileAction.GoToProfile: + this.router.navigate(["/myapp/profile"]); + break; + case UserProfileAction.LogOut: + this.logout(); + break; + default: break; + } + } + }); } ngOnDestroy() { diff --git a/src/app/admin/admin.component.html b/src/app/admin/admin.component.html index e2b6168..0fdf35c 100644 --- a/src/app/admin/admin.component.html +++ b/src/app/admin/admin.component.html @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/src/app/admin/admin.module.ts b/src/app/admin/admin.module.ts index 4e43349..e4c8622 100644 --- a/src/app/admin/admin.module.ts +++ b/src/app/admin/admin.module.ts @@ -6,10 +6,7 @@ import { AdminComponent } from './admin.component'; import { NbMenuModule, NbInputModule, NbCardModule, NbButtonModule, NbActionsModule, NbCheckboxModule, NbRadioModule, NbDatepickerModule, NbSelectModule, NbIconModule, NbTagModule, NbStepperModule, NbListModule, NbSpinnerModule, NbDialogModule, NbUserModule } from '@nebular/theme'; import { ThemeModule } from '../@theme/theme.module'; import { FormsModule } from '@angular/forms'; -import { BestListDlgComponent } from './happiness-groups/best-list-dlg/best-list-dlg.component'; import { AlertDlgModule } from '../ui/alert-dlg/alert-dlg.module'; -import { HappinessWeekEditorComponent } from './happiness-groups/happiness-week-editor/happiness-week-editor.component'; -import { HappinessWeekListDlgComponent } from './happiness-groups/happiness-week-list-dlg/happiness-week-list-dlg.component'; import { CellGroupRoutineEventsComponent } from './cell-group-routine-events/cell-group-routine-events.component'; import { FancyTableModule } from '../ui/fancy-table/fancy-table.module'; import { FamilyMembersComponent } from './family-members/family-members.component'; @@ -26,14 +23,9 @@ import { MaskDirectiveModule } from '../directives/mask-directive/mask-directive import { DateInputModule } from '../ui/date-input/date-input.module'; import { LineMessagingAccountComponent } from './lines/line-messaging-account/line-messaging-account.component'; import { LineMessagingAccountEditorComponent } from './lines/line-messaging-account-editor/line-messaging-account-editor.component'; -import { WeekTaskEditorComponent } from './happiness-groups/week-task-editor/week-task-editor.component'; - @NgModule({ declarations: [ AdminComponent, - BestListDlgComponent, - HappinessWeekEditorComponent, - HappinessWeekListDlgComponent, CellGroupRoutineEventsComponent, FamilyMembersComponent, FamilyMemberEditorComponent, @@ -44,7 +36,7 @@ import { WeekTaskEditorComponent } from './happiness-groups/week-task-editor/wee LogDetailComponent, LineMessagingAccountComponent, LineMessagingAccountEditorComponent, - WeekTaskEditorComponent], + ], imports: [ CommonModule, FormsModule, diff --git a/src/app/admin/cell-group-routine-events/cell-group-routine-events.component.ts b/src/app/admin/cell-group-routine-events/cell-group-routine-events.component.ts index 2458e14..deef103 100644 --- a/src/app/admin/cell-group-routine-events/cell-group-routine-events.component.ts +++ b/src/app/admin/cell-group-routine-events/cell-group-routine-events.component.ts @@ -4,10 +4,10 @@ import { NbDialogService } from '@nebular/theme'; import { Observable } from 'rxjs'; import { first } from 'rxjs/operators'; import { inherits } from 'util'; -import { StateService } from '../../@core/utils'; import { CellGroupRoutineEvents } from '../../entity/CellGroupRoutineEvents'; import { CellGroupRoutineEventsService } from '../../services/crudServices/cell-group-routine-events.service'; import { MsgBoxService } from '../../services/msg-box.service'; +import { StateService } from '../../services/state.service'; import { FancySettings } from '../../ui/fancy-table/fancy-settings.model'; import { FancyTableComponent } from '../../ui/fancy-table/fancy-table.component'; import { ObjectUtils } from '../../utilities/object-utils'; diff --git a/src/app/admin/family-members/assign-member-cell-group/assign-member-cell-group.component.ts b/src/app/admin/family-members/assign-member-cell-group/assign-member-cell-group.component.ts index 79cc679..8533415 100644 --- a/src/app/admin/family-members/assign-member-cell-group/assign-member-cell-group.component.ts +++ b/src/app/admin/family-members/assign-member-cell-group/assign-member-cell-group.component.ts @@ -3,10 +3,10 @@ import { NbDialogRef } from '@nebular/theme'; import { DropDownOption } from '../../../entity/dropDownOption'; import { DomainMemberRelationship, PastoralDomain } from '../../../entity/PastoralDomain'; import { DialogComponent } from '../../../pages/modal-overlays/dialog/dialog.component'; -import { DomainMemberShipService } from '../../../services/crudServices/pastoral-domain.service'; import { ArrayUtils } from '../../../utilities/array-utils'; import { first } from "rxjs/operators" import { FamilyMember } from '../../../entity/Member'; +import { DomainMemberShipService } from '../../../services/crudServices/domain-member-ship.service'; @Component({ selector: 'ngx-assign-member-cell-group', diff --git a/src/app/admin/family-members/family-members.component.ts b/src/app/admin/family-members/family-members.component.ts index 81d163f..a935f0d 100644 --- a/src/app/admin/family-members/family-members.component.ts +++ b/src/app/admin/family-members/family-members.component.ts @@ -3,12 +3,12 @@ import { ActivatedRoute } from '@angular/router'; import { NbDialogService } from '@nebular/theme'; import { Observable } from 'rxjs'; import { first } from 'rxjs/operators'; -import { StateService } from '../../@core/utils'; import { FamilyMember, Gender } from '../../entity/Member'; import { PastoralDomain } from '../../entity/PastoralDomain'; import { FamilyMemberService } from '../../services/crudServices/family-member.service'; import { PastoralDomainService } from '../../services/crudServices/pastoral-domain.service'; import { MsgBoxService } from '../../services/msg-box.service'; +import { StateService } from '../../services/state.service'; import { FancySettings } from '../../ui/fancy-table/fancy-settings.model'; import { FancyTableComponent } from '../../ui/fancy-table/fancy-table.component'; import { ObjectUtils } from '../../utilities/object-utils'; diff --git a/src/app/admin/happiness-groups/best-list-dlg/best-list-dlg.component.scss b/src/app/admin/happiness-groups/best-list-dlg/best-list-dlg.component.scss deleted file mode 100644 index 12d612c..0000000 --- a/src/app/admin/happiness-groups/best-list-dlg/best-list-dlg.component.scss +++ /dev/null @@ -1,4 +0,0 @@ -nb-card { - max-height: 90vh; - width: 700px; -} diff --git a/src/app/admin/happiness-groups/best-list-dlg/best-list-dlg.component.ts b/src/app/admin/happiness-groups/best-list-dlg/best-list-dlg.component.ts deleted file mode 100644 index 9332758..0000000 --- a/src/app/admin/happiness-groups/best-list-dlg/best-list-dlg.component.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { NbDialogRef, NbToastrService } from '@nebular/theme'; -import { first } from 'rxjs/operators'; -import { environment } from '../../../../environments/environment'; -import { HappinessBEST } from '../../../entity/HappinessGroup'; -import { PastoralDomain } from '../../../entity/PastoralDomain'; -import { BestService } from '../../../services/crudServices/best.service'; -import { HappinessGroupService } from '../../../services/crudServices/happiness-group.service'; -import { LineGroup, LineService } from '../../../services/line.service'; -import { MsgBoxService } from '../../../services/msg-box.service'; -import { ADButtons, AlertDlgComponent } from '../../../ui/alert-dlg/alert-dlg.component'; - - - -@Component({ - selector: 'ngx-best-list-dlg', - templateUrl: './best-list-dlg.component.html', - styleUrls: ['./best-list-dlg.component.scss'] -}) -export class BestListDlgComponent implements OnInit { - - processing: boolean = false; - isAdding: boolean = false; - group: PastoralDomain; - datum: HappinessBEST; - constructor( - private dlgRef: NbDialogRef, - private msgBpxService: MsgBoxService, - private happinessGroupService: HappinessGroupService, - private toastrService: NbToastrService, - private bestService: BestService, - private lineService: LineService - ) { } - - ngOnInit(): void { - this.group.bests = this.group.bests.sort((a, b) => 0 - (a.name < b.name ? 1 : -1)); - } - - close() { - this.dlgRef.close(); - } - update() { - this.dlgRef.close(this.datum); - } - addBest() { - this.msgBpxService.showInputbox('Add Best', 'Please input Best\'s Name').pipe(first()).subscribe(result => { - if (result) { - let obj = { groupId: this.group.id, id: '', name: result } as HappinessBEST; - this.bestService.createOrUpdate(obj).pipe(first()).subscribe(result => { - this.dlgRef.close(); - }); - } - }); - } - - copyBestUrl(best: HappinessBEST) { - - var dummy = document.createElement("textarea"); - document.body.appendChild(dummy); - dummy.value = `${environment.invitationUrl}${best.id}`; - dummy.select(); - document.execCommand("copy"); - document.body.removeChild(dummy); - this.toastrService.success(dummy.value, "複製地址至剪貼簿!"); - } - copyBestList() { - let list = "".concat(...this.group.bests.map(b => `${b.name}\t\t: ${environment.invitationUrl}${b.id}\r\n`)); - var dummy = document.createElement("textarea"); - document.body.appendChild(dummy); - dummy.value = list; - dummy.select(); - document.execCommand("copy"); - document.body.removeChild(dummy); - this.toastrService.success(dummy.value, "複製地址至剪貼簿!"); - - this.lineService.pushLineMessage(LineGroup.Chris, list); - - } - downloadBestQRCode(best: HappinessBEST) { - - this.happinessGroupService.getBestQrCode(best.name + ".png", best.id); - } - -} diff --git a/src/app/admin/happiness-groups/happiness-week-list-dlg/happiness-week-list-dlg.component.scss b/src/app/admin/happiness-groups/happiness-week-list-dlg/happiness-week-list-dlg.component.scss deleted file mode 100644 index 12d612c..0000000 --- a/src/app/admin/happiness-groups/happiness-week-list-dlg/happiness-week-list-dlg.component.scss +++ /dev/null @@ -1,4 +0,0 @@ -nb-card { - max-height: 90vh; - width: 700px; -} diff --git a/src/app/admin/happiness-groups/happiness-week-list-dlg/happiness-week-list-dlg.component.ts b/src/app/admin/happiness-groups/happiness-week-list-dlg/happiness-week-list-dlg.component.ts deleted file mode 100644 index 7158aa2..0000000 --- a/src/app/admin/happiness-groups/happiness-week-list-dlg/happiness-week-list-dlg.component.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { NbDialogRef, NbDialogService } from '@nebular/theme'; -import { first } from 'rxjs/operators'; -import { HappinessWeek } from '../../../entity/HappinessGroup'; -import { PastoralDomain } from '../../../entity/PastoralDomain'; -import { NumberUtils } from '../../../utilities/number-utils'; -import { HappinessWeekEditorComponent } from '../happiness-week-editor/happiness-week-editor.component'; -import { WeekTaskEditorComponent } from '../week-task-editor/week-task-editor.component'; - -@Component({ - selector: 'ngx-happiness-week-list-dlg', - templateUrl: './happiness-week-list-dlg.component.html', - styleUrls: ['./happiness-week-list-dlg.component.scss'] -}) -export class HappinessWeekListDlgComponent implements OnInit { - - group: PastoralDomain; - constructor( - private dlgRef: NbDialogRef, - private dlgService: NbDialogService - ) { } - - ngOnInit(): void { - - } - close() { - this.dlgRef.close(); - } - openEditDlg(week: HappinessWeek) { - this.dlgService.open(HappinessWeekEditorComponent, { - context: { - data: week - } - }).onClose.pipe(first()).subscribe(result => { - if (result) this.close(); - }); - } - openTaskDlg(week: HappinessWeek) { - this.dlgService.open(WeekTaskEditorComponent, { - context: { - data: week, - allData: this.group.happinessWeeks - } - }).onClose.pipe(first()).subscribe(result => { - - }); - - } - weekDisplay(seq: number) { - return `W${seq} ${this.group.happinessWeeks[seq - 1].topic}`; - } -} diff --git a/src/app/admin/happiness-groups/week-task-editor/week-task-editor.component.html b/src/app/admin/happiness-groups/week-task-editor/week-task-editor.component.html deleted file mode 100644 index 14d01f2..0000000 --- a/src/app/admin/happiness-groups/week-task-editor/week-task-editor.component.html +++ /dev/null @@ -1,38 +0,0 @@ -
- - - 第 {{data.seq}} 周 {{data.topic}} 分工 - - -
-
-
- - - -
-
- -
-
- - -
-
-
- -
- - - - -
-
\ No newline at end of file diff --git a/src/app/admin/happiness-groups/week-task-editor/week-task-editor.component.ts b/src/app/admin/happiness-groups/week-task-editor/week-task-editor.component.ts deleted file mode 100644 index 19b8e5d..0000000 --- a/src/app/admin/happiness-groups/week-task-editor/week-task-editor.component.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { NbDialogRef } from '@nebular/theme'; -import { HappinessTask, HappinessTaskType, HappinessWeek } from '../../../entity/HappinessGroup'; -import { HappinessTaskService } from '../../../services/crudServices/happiness-group.service'; -import { first } from 'rxjs/operators'; -import { DropDownOption } from '../../../entity/dropDownOption'; -import { StringUtils } from '../../../utilities/string-utils'; - -@Component({ - selector: 'ngx-week-task-editor', - templateUrl: './week-task-editor.component.html', - styleUrls: ['./week-task-editor.component.scss'] -}) -export class WeekTaskEditorComponent implements OnInit { - processing: boolean = false; - allData: HappinessWeek[]; - data: HappinessWeek; - taskrOptions: DropDownOption[] = []; - constructor( - private happinessTaskService: HappinessTaskService, - private dlgRef: NbDialogRef - ) { - - } - ngOnInit(): void { - if (this.data.tasks.length == 0) { - this.data.tasks = []; - for (let i = HappinessTaskType.IceBreak; i <= HappinessTaskType.Dessert; i++) { - this.data.tasks.push( - { - weekId: this.data.id, - id: 'new', - type: i as HappinessTaskType, - tasker: '', - content: '' - } as HappinessTask - - ) - } - } - let names = [] as string[]; - this.allData.forEach(week => { - if (week.tasks) { - names = names.concat(week.tasks.map(t => t.tasker.trim())); - - } - }); - this.taskrOptions = names.filter(function (item, pos) { - return !StringUtils.isNullOrWhitespace(item) && names.indexOf(item) == pos; - }).map(name => new DropDownOption(name, name)); - } - - close() { - this.dlgRef.close(); - } - update() { - if (this.processing == false) { - - this.processing = true; - - this.happinessTaskService.createOrUpdateAll(this.data.tasks).pipe(first()).subscribe(result => { - this.processing = false; - this.dlgRef.close(true); - }); - } - } - - getTaskTitle(t: HappinessTaskType) { - switch (t) { - case HappinessTaskType.IceBreak: return '帶遊戲'; - case HappinessTaskType.Worship: return '唱歌'; - case HappinessTaskType.Testimony: return '見證'; - case HappinessTaskType.Message: return '信息'; - case HappinessTaskType.Gift: return '準備禮物'; - case HappinessTaskType.Dessert: return '準備點心'; - default: break; - } - } -} \ No newline at end of file diff --git a/src/app/admin/lines/line-messaging-account-editor/line-messaging-account-editor.component.ts b/src/app/admin/lines/line-messaging-account-editor/line-messaging-account-editor.component.ts index b6924b2..557c774 100644 --- a/src/app/admin/lines/line-messaging-account-editor/line-messaging-account-editor.component.ts +++ b/src/app/admin/lines/line-messaging-account-editor/line-messaging-account-editor.component.ts @@ -33,7 +33,7 @@ export class LineMessagingAccountEditorComponent implements OnInit { this.processing = true; - let func = this.isAdding ? this.lineMessagingAccountService.createOrUpdate(this.data) : this.lineMessagingAccountService.update(this.data); + let func = this.lineMessagingAccountService.createOrUpdate(this.data);//this.isAdding ? this.lineMessagingAccountService.createOrUpdate(this.data) : this.lineMessagingAccountService.update(this.data); func.pipe(first()).subscribe(result => { this.processing = false; if (result) { diff --git a/src/app/admin/logs/logs.component.ts b/src/app/admin/logs/logs.component.ts index ad51473..9170494 100644 --- a/src/app/admin/logs/logs.component.ts +++ b/src/app/admin/logs/logs.component.ts @@ -3,11 +3,11 @@ import { ActivatedRoute } from '@angular/router'; import { NbDialogService } from '@nebular/theme'; import { Observable } from 'rxjs'; import { first } from 'rxjs/operators'; -import { StateService } from '../../@core/utils'; import { Log, LogLevel } from '../../entity/Log'; import { ScreenBase } from '../../ScreenBase'; import { LogService } from '../../services/crudServices/log.service'; import { MsgBoxService } from '../../services/msg-box.service'; +import { StateService } from '../../services/state.service'; import { FancyTag } from '../../ui/fancy-table/fancy-row-column.model'; import { FancySettings } from '../../ui/fancy-table/fancy-settings.model'; import { FancyTableComponent } from '../../ui/fancy-table/fancy-table.component'; diff --git a/src/app/admin/pastoral-domains/pastoral-domains.component.ts b/src/app/admin/pastoral-domains/pastoral-domains.component.ts index f0256ba..0c8972f 100644 --- a/src/app/admin/pastoral-domains/pastoral-domains.component.ts +++ b/src/app/admin/pastoral-domains/pastoral-domains.component.ts @@ -3,17 +3,18 @@ import { ActivatedRoute } from '@angular/router'; import { NbDialogService } from '@nebular/theme'; import { Observable } from 'rxjs'; import { first } from 'rxjs/operators'; -import { StateService } from '../../@core/utils'; import { FamilyMember } from '../../entity/Member'; import { DomainType, PastoralDomain } from '../../entity/PastoralDomain'; +import { BestListDlgComponent } from '../../happiness/best-list-dlg/best-list-dlg.component'; +import { HappinessWeekListDlgComponent } from '../../happiness/happiness-week-list-dlg/happiness-week-list-dlg.component'; +import { DomainMemberShipService } from '../../services/crudServices/domain-member-ship.service'; import { FamilyMemberService } from '../../services/crudServices/family-member.service'; import { PastoralDomainService } from '../../services/crudServices/pastoral-domain.service'; import { MsgBoxService } from '../../services/msg-box.service'; +import { StateService } from '../../services/state.service'; import { FancySettings } from '../../ui/fancy-table/fancy-settings.model'; import { FancyTableComponent } from '../../ui/fancy-table/fancy-table.component'; import { ObjectUtils } from '../../utilities/object-utils'; -import { BestListDlgComponent } from '../happiness-groups/best-list-dlg/best-list-dlg.component'; -import { HappinessWeekListDlgComponent } from '../happiness-groups/happiness-week-list-dlg/happiness-week-list-dlg.component'; import { PastoralDomainEditorComponent } from './pastoral-domain-editor/pastoral-domain-editor.component'; @Component({ @@ -35,7 +36,8 @@ export class PastoralDomainsComponent implements OnInit { private dlgService: NbDialogService, protected stateService: StateService, protected route: ActivatedRoute, - private memberService: FamilyMemberService + private memberService: FamilyMemberService, + private memberShipService: DomainMemberShipService ) { } @@ -87,6 +89,15 @@ export class PastoralDomainsComponent implements OnInit { callback: (datum, element) => { this.openHappinessWeekListDlg(datum); }, + }, + { + enabled: true, + id: 'members', + title: 'Members', + icon: 'people-outline', + callback: (datum, element) => { + this.openMemberAssignDlg(datum); + }, } ], onContextMenuOpening: (datum, menuItems) => { @@ -94,9 +105,18 @@ export class PastoralDomainsComponent implements OnInit { menuItems.find(i => i.id == 'edit').visible = !!datum; menuItems.find(i => i.id == 'happinessBest').visible = datum.type == DomainType.HappinessGroup; menuItems.find(i => i.id == 'happinessWeek').visible = datum.type == DomainType.HappinessGroup; + //menuItems.find(i => i.id == 'members').visible = datum.type == DomainType.HappinessGroup; return datum; }, columns: [ + { + name: 'type', + title: 'Type', + type: 'number', + group: true, + visible: false, + groupValuePrepareFunction: (v) => this.getDomainTypeName(v.type) + }, { name: 'name', title: 'Name', @@ -108,7 +128,7 @@ export class PastoralDomainsComponent implements OnInit { name: 'description', title: 'Description', type: 'text', - widthPx: 200, + widthPct: 70, //valuePrepareFunction: (item) => , }, { @@ -136,7 +156,6 @@ export class PastoralDomainsComponent implements OnInit { // }, ], - }; //#endregion @@ -222,5 +241,33 @@ export class PastoralDomainsComponent implements OnInit { }); } + private getDomainTypeName(type: DomainType): string { + switch (type) { + case DomainType.CellGroup: return "細胞小組"; + case DomainType.HappinessGroup: return "幸福小組"; + case DomainType.CellGroupCoworker: return "細胞同工"; + case DomainType.ChurchCoworker: return "教會事工"; + case DomainType.Administrator: return "管理員"; + default: break; + } + } + private openMemberAssignDlg(datum: PastoralDomain) { + + // this.msgBoxService.showListBox( + // `Members in ${datum.name}`, + // this.members, + // 'id', + // datum.familyMembers.map(m => m.id), + // (e) => `${e.firstName} ${e.lastName} (${e.email})` + // ).pipe(first()).subscribe(result => { + // if (result) { + + // datum.familyMembers = result; + // this.memberShipService.updateMembersInGroup(datum).pipe(first()).subscribe(result => { + + // }); + // } + // }); + } } diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index dba215b..3d6c7c6 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -77,7 +77,7 @@ export const routes: Routes = [ } }, { - path: 'CellGroup', loadChildren: () => import('./cell-group/cell-group.module').then(m => m.CellGroupModule), + path: 'myapp', loadChildren: () => import('./cell-group/cell-group.module').then(m => m.CellGroupModule), canActivateChild: [AuthGuardService], data: { roles: Role.All diff --git a/src/app/cell-group/MyAppBase.ts b/src/app/cell-group/MyAppBase.ts new file mode 100644 index 0000000..e2a0bea --- /dev/null +++ b/src/app/cell-group/MyAppBase.ts @@ -0,0 +1,93 @@ +import { ActivatedRoute } from "@angular/router"; +import { basename } from "path"; +import { Observable, Subject } from "rxjs"; +import { ScreenBase } from "../ScreenBase"; +import { ICrudService } from "../services/crudServices/crud.service"; +import { PastoralDomainService } from "../services/crudServices/pastoral-domain.service"; +import { StateService } from "../services/state.service"; +import { first } from 'rxjs/operators'; +import { PastoralDomain } from "../entity/PastoralDomain"; +import { Injectable } from "@angular/core"; + +@Injectable() +export abstract class MyAppBase { + + /** + * + */ + constructor( + protected stateService: StateService, + protected route: ActivatedRoute, + protected pastoralDomainService: PastoralDomainService + ) { + // super(pastoralDomainService, stateService, route); + // this.isSnapshotView = true; + } + isLoading: boolean = true; + redirectIfNoDomains: boolean = true; + + pageGroupId: string; + + private domainInitialized = new Subject();; + ngOnInit(): void { + + this.isLoading = true; + // this.route.paramMap.subscribe((params: ParamMap) => { + // this.id = +params.get('id') + // }); + this.route.paramMap.pipe(first()).subscribe(params => { + if (params.get('groupId')) { + this.pageGroupId = params.get('groupId'); + } + + this.pastoralDomainService.initialized.takeUntil(this.domainInitialized).subscribe(result => { + if (result) { + this.domainInitialized.next(); + if (this.redirectIfNoDomains) { + if (this.pageGroupId && !this.domains.find(d => d.id == this.pageGroupId)) { + this.pastoralDomainService.joinDomain(this.pageGroupId).pipe(first()).subscribe(result => { + this.pageOnInit(); + }); + return; + } else if (this.domains.length == 0) { + //TODO:SetUser + return; + } + } + + this.pageOnInit(); + } + }); + + }); + } + + public get domains(): PastoralDomain[] { + return this.pastoralDomainService.domains; + } + + abstract pageOnInit(): void; + + get saveMethod(): Observable { + throw new Error("Method not implemented."); + } + + public get happinessGroup(): PastoralDomain { + return this.pastoralDomainService.myHappinessGroup; + } + public get cellGroup(): PastoralDomain { + return this.pastoralDomainService.myCellGroup; + } + + public get currentDomain(): PastoralDomain { + return this.domains.find(d => d.id == this.pageGroupId); + } + public get currentDomainName(): string { + if (this.domains && this.pageGroupId) { + //let group = this.domains.find(d => d.id == this.pageGroupId); + + return this.domains.find(d => d.id == this.pageGroupId)?.name; + } + return ""; + } +} \ No newline at end of file diff --git a/src/app/cell-group/cell-group-routing.module.ts b/src/app/cell-group/cell-group-routing.module.ts index 38d06da..27f9f95 100644 --- a/src/app/cell-group/cell-group-routing.module.ts +++ b/src/app/cell-group/cell-group-routing.module.ts @@ -2,25 +2,58 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { NbMenuItem } from '@nebular/theme'; import { Role } from '../entity/Auth'; +import { DomainType } from '../entity/PastoralDomain'; import { CellGroupComponent } from './cell-group.component'; import { DinnerComponent } from './dinner/dinner.component'; +import { FinanceComponent } from './finance/finance.component'; import { GoogleLoginComponent } from './google-login/google-login.component'; +import { BestListComponent, HappinessWeekListComponent } from './happiness-group/happiness-group.component'; import { PrayerComponent } from './prayer/prayer.component'; +import { UserProfileComponent } from './user-profile/user-profile.component'; export class CellGroupRoutingConfig { public static MENU_ITEMS: NbMenuItem[] = [ { - title: '小組禱告', + title: '細胞小組', icon: 'people-outline', - link: '/CellGroup/prayer', - home: true, + children: [ + + { + title: '小組禱告', + //icon: 'people-outline', + link: '/myapp/prayer' + }, + { + title: '小組晚餐', + //icon: 'people-outline', + link: '/myapp/dinner', + }, + ], + data: DomainType.CellGroup }, { - title: '小組晚餐', - icon: 'people-outline', - link: '/CellGroup/dinner', - }, + title: '幸福小組', + icon: 'smiling-face-outline', + children: [ + { + title: 'Bests', + //icon: 'people-outline', + link: '/myapp/bests' + }, + { + title: '幸福周', + //icon: 'people-outline', + link: '/myapp/happinessWeeks', + }, + { + title: '財務表', + //icon: 'people-outline', + link: '/myapp/finance', + }, + ], + data: DomainType.HappinessGroup + }, ] } const routes: Routes = [ @@ -29,7 +62,16 @@ const routes: Routes = [ children: [ { path: 'dinner', component: DinnerComponent, }, + { path: 'dinner/:groupId', component: DinnerComponent, }, { path: 'prayer', component: PrayerComponent, }, + { path: 'prayer/:groupId', component: PrayerComponent, }, + { path: 'profile', component: UserProfileComponent, }, + { path: 'bests', component: BestListComponent, }, + { path: 'bests/:groupId', component: BestListComponent, }, + { path: 'happinessWeeks', component: HappinessWeekListComponent, }, + { path: 'happinessWeeks/:groupId', component: HappinessWeekListComponent, }, + { path: 'finance/:groupId', component: FinanceComponent, }, + { path: 'management', component: GoogleLoginComponent, data: { diff --git a/src/app/cell-group/cell-group.component.html b/src/app/cell-group/cell-group.component.html index e2b6168..0fdf35c 100644 --- a/src/app/cell-group/cell-group.component.html +++ b/src/app/cell-group/cell-group.component.html @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/src/app/cell-group/cell-group.component.ts b/src/app/cell-group/cell-group.component.ts index 1374a2e..221bee1 100644 --- a/src/app/cell-group/cell-group.component.ts +++ b/src/app/cell-group/cell-group.component.ts @@ -1,5 +1,9 @@ import { Component, OnInit } from '@angular/core'; +import { NbMenuItem } from '@nebular/theme'; +import { PastoralDomainService } from '../services/crudServices/pastoral-domain.service'; +import { ObjectUtils } from '../utilities/object-utils'; import { CellGroupRoutingConfig } from './cell-group-routing.module'; +import { first } from 'rxjs/operators'; @Component({ selector: 'ngx-cell-group', @@ -8,10 +12,45 @@ import { CellGroupRoutingConfig } from './cell-group-routing.module'; }) export class CellGroupComponent implements OnInit { - MENU_ITEMS = CellGroupRoutingConfig.MENU_ITEMS; - constructor() { } - - ngOnInit(): void { + MENU_ITEMS = ObjectUtils.CloneValue(CellGroupRoutingConfig.MENU_ITEMS); + constructor( + private pastoralDomainService: PastoralDomainService + ) { + let subscription = pastoralDomainService.initialized.subscribe(result => { + if (result) { + this.initializeSideMenu(); + subscription.unsubscribe(); + } + }); } + ngOnInit(): void { + + } + + private initializeSideMenu() { + + for (let i = 0; i < this.MENU_ITEMS.length; i++) { + const item = this.MENU_ITEMS[i]; + this.checkDisplayItem(item); + } + } + private checkDisplayItem(item: NbMenuItem) { + if (item.data != undefined) { + var group = this.pastoralDomainService.domains.find(d => d.type == item.data); + if (!group) { + item.hidden = true; + return; + } + item.title = `${group.name}`; + item.children.forEach(element => { + element.link += `/${group.id}`; + }); + + } else if (item.children) { + item.children.forEach(element => { + this.checkDisplayItem(element); + }); + } + } } diff --git a/src/app/cell-group/cell-group.module.ts b/src/app/cell-group/cell-group.module.ts index 04bdc6b..6daa033 100644 --- a/src/app/cell-group/cell-group.module.ts +++ b/src/app/cell-group/cell-group.module.ts @@ -5,11 +5,19 @@ import { CellGroupRoutingModule } from './cell-group-routing.module'; import { CellGroupComponent } from './cell-group.component'; import { DinnerComponent } from './dinner/dinner.component'; import { FormsModule } from '@angular/forms'; -import { NbButtonModule, NbCardModule, NbIconModule, NbInputModule, NbMenuModule, NbSpinnerModule, NbToastrModule, NbToggleModule } from '@nebular/theme'; +import { NbActionsModule, NbButtonModule, NbCardModule, NbCheckboxModule, NbIconModule, NbInputModule, NbMenuModule, NbSpinnerModule, NbToastrModule, NbToggleModule } from '@nebular/theme'; import { ThemeModule } from '../@theme/theme.module'; import { GoogleLoginComponent } from './google-login/google-login.component'; import { PrayerComponent } from './prayer/prayer.component'; import { UserProfileComponent } from './user-profile/user-profile.component'; +import { DateInputModule } from '../ui/date-input/date-input.module'; +import { DropDownListModule } from '../ui/drop-down-list/drop-down-list.module'; +import { HappinessModule } from '../happiness/happiness.module'; +import { BestListComponent, HappinessWeekListComponent } from './happiness-group/happiness-group.component'; +import { JoinDomainComponent } from './join-domain/join-domain.component'; +import { FinanceComponent } from './finance/finance.component'; +import { AddContributionDlgComponent } from './finance/add-contribution-dlg/add-contribution-dlg.component'; +import { FancyTableModule } from '../ui/fancy-table/fancy-table.module'; @NgModule({ @@ -18,7 +26,12 @@ import { UserProfileComponent } from './user-profile/user-profile.component'; DinnerComponent, GoogleLoginComponent, PrayerComponent, - UserProfileComponent + UserProfileComponent, + BestListComponent, + HappinessWeekListComponent, + JoinDomainComponent, + FinanceComponent, + AddContributionDlgComponent ], imports: [ ThemeModule, @@ -32,8 +45,13 @@ import { UserProfileComponent } from './user-profile/user-profile.component'; NbToastrModule, NbToggleModule, NbIconModule, - NbMenuModule - + NbMenuModule, + NbActionsModule, + DateInputModule, + NbCheckboxModule, + DropDownListModule, + HappinessModule, + FancyTableModule ] }) export class CellGroupModule { } diff --git a/src/app/cell-group/dinner/dinner.component.ts b/src/app/cell-group/dinner/dinner.component.ts index 56c559a..a175b44 100644 --- a/src/app/cell-group/dinner/dinner.component.ts +++ b/src/app/cell-group/dinner/dinner.component.ts @@ -11,14 +11,17 @@ import { AuthService } from '../../services/auth.service'; import { DateUtils } from '../../utilities/date-utils'; import { NumberUtils } from '../../utilities/number-utils'; import { CellGroupRoutineEventsService } from '../../services/crudServices/cell-group-routine-events.service'; +import { ActivatedRoute } from '@angular/router'; +import { PastoralDomainService } from '../../services/crudServices/pastoral-domain.service'; +import { MyAppBase } from '../MyAppBase'; +import { StateService } from '../../services/state.service'; @Component({ selector: 'ngx-dinner', templateUrl: './dinner.component.html', styleUrls: ['./dinner.component.scss'] }) -export class DinnerComponent implements OnInit { - +export class DinnerComponent extends MyAppBase { constructor( private cellGroupRoutineEventsService: CellGroupRoutineEventsService, private messageService: MsgBoxService, @@ -26,10 +29,12 @@ export class DinnerComponent implements OnInit { private sessionService: SessionService, private lineService: LineService, private cdRef: ChangeDetectorRef, - private headerService: HeaderService, - private authService: AuthService + private authService: AuthService, + protected stateService: StateService, + protected route: ActivatedRoute, + protected pastoralDomainService: PastoralDomainService ) { - + super(stateService, route, pastoralDomainService); } cellGroupEvent: CellGroupRoutineEvents; @@ -40,10 +45,12 @@ export class DinnerComponent implements OnInit { isLoading: boolean = true; processing: boolean = false; - ngOnInit(): void { - this.headerService.setHeader("晚宴系統") + pageOnInit(): void { + this.stateService.SetPageTitle("晚宴系統"); this.getAllData(); + } + getAllData() { this.isLoading = true; @@ -70,7 +77,7 @@ export class DinnerComponent implements OnInit { this.processing = false; this.toastrService.success('菜單更新完成!'); - this.lineService.pushCommandMessage('Cac4ac5a8d7fc52daa444d71dc7c360a9', 'dinner'); + this.lineService.pushCommandMessage(this.cellGroupEvent.pastoralDomainId, 'dinner'); }); } diff --git a/src/app/cell-group/finance/add-contribution-dlg/add-contribution-dlg.component.html b/src/app/cell-group/finance/add-contribution-dlg/add-contribution-dlg.component.html new file mode 100644 index 0000000..b0b3026 --- /dev/null +++ b/src/app/cell-group/finance/add-contribution-dlg/add-contribution-dlg.component.html @@ -0,0 +1,36 @@ + + + 新增奉獻 + + +
+
+
+ + + +
+
+ +
+
+ + +
+
+
+
+ + +
+
+
+
+ + + + +
\ No newline at end of file diff --git a/src/app/admin/happiness-groups/week-task-editor/week-task-editor.component.scss b/src/app/cell-group/finance/add-contribution-dlg/add-contribution-dlg.component.scss similarity index 100% rename from src/app/admin/happiness-groups/week-task-editor/week-task-editor.component.scss rename to src/app/cell-group/finance/add-contribution-dlg/add-contribution-dlg.component.scss diff --git a/src/app/cell-group/finance/add-contribution-dlg/add-contribution-dlg.component.spec.ts b/src/app/cell-group/finance/add-contribution-dlg/add-contribution-dlg.component.spec.ts new file mode 100644 index 0000000..22123cf --- /dev/null +++ b/src/app/cell-group/finance/add-contribution-dlg/add-contribution-dlg.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AddContributionDlgComponent } from './add-contribution-dlg.component'; + +describe('AddContributionDlgComponent', () => { + let component: AddContributionDlgComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AddContributionDlgComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AddContributionDlgComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/cell-group/finance/add-contribution-dlg/add-contribution-dlg.component.ts b/src/app/cell-group/finance/add-contribution-dlg/add-contribution-dlg.component.ts new file mode 100644 index 0000000..761cae5 --- /dev/null +++ b/src/app/cell-group/finance/add-contribution-dlg/add-contribution-dlg.component.ts @@ -0,0 +1,33 @@ +import { Component, OnInit } from '@angular/core'; +import { NbDialogRef } from '@nebular/theme'; +import { Contribution } from '../../../entity/contribution.model'; +import { DropDownOption } from '../../../entity/dropDownOption'; +import { AuthService } from '../../../services/auth.service'; + +@Component({ + selector: 'ngx-add-contribution-dlg', + templateUrl: './add-contribution-dlg.component.html', + styleUrls: ['./add-contribution-dlg.component.scss'] +}) +export class AddContributionDlgComponent implements OnInit { + + taskrOptions: DropDownOption[] = []; + contribution: Contribution; + constructor( + private authService: AuthService, + private dlgRef: NbDialogRef + ) { } + + ngOnInit(): void { + this.contribution = { time: new Date() } as Contribution; + } + close() { + this.dlgRef.close(); + } + submit() { + if (this.contribution.contributor && this.contribution.amount > 0) { + this.dlgRef.close(this.contribution); + } + } + +} diff --git a/src/app/cell-group/finance/finance.component.html b/src/app/cell-group/finance/finance.component.html new file mode 100644 index 0000000..cf2dc7a --- /dev/null +++ b/src/app/cell-group/finance/finance.component.html @@ -0,0 +1,13 @@ + + + {{currentDomainName}} 財務表 + + + + + + + + + + \ No newline at end of file diff --git a/src/app/cell-group/finance/finance.component.scss b/src/app/cell-group/finance/finance.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/cell-group/finance/finance.component.spec.ts b/src/app/cell-group/finance/finance.component.spec.ts new file mode 100644 index 0000000..8159d4d --- /dev/null +++ b/src/app/cell-group/finance/finance.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FinanceComponent } from './finance.component'; + +describe('FinanceComponent', () => { + let component: FinanceComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ FinanceComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(FinanceComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/cell-group/finance/finance.component.ts b/src/app/cell-group/finance/finance.component.ts new file mode 100644 index 0000000..99cc62d --- /dev/null +++ b/src/app/cell-group/finance/finance.component.ts @@ -0,0 +1,208 @@ +import { ChangeDetectorRef, Component, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { NbDialogService, NbToastrService } from '@nebular/theme'; +import { Contribution } from '../../entity/contribution.model'; +import { AuthService } from '../../services/auth.service'; +import { ContributionService } from '../../services/crudServices/contribution.service'; +import { PastoralDomainService } from '../../services/crudServices/pastoral-domain.service'; +import { LineService } from '../../services/line.service'; +import { MsgBoxService } from '../../services/msg-box.service'; +import { SessionService } from '../../services/session.service'; +import { StateService } from '../../services/state.service'; +import { MyAppBase } from '../MyAppBase'; +import { AddContributionDlgComponent } from './add-contribution-dlg/add-contribution-dlg.component'; +import { first } from 'rxjs/operators'; +import { FancySettings } from '../../ui/fancy-table/fancy-settings.model'; +import { ObjectUtils } from '../../utilities/object-utils'; +import { NumberUtils } from '../../utilities/number-utils'; +import { StringUtils } from '../../utilities/string-utils'; + +@Component({ + selector: 'ngx-finance', + templateUrl: './finance.component.html', + styleUrls: ['./finance.component.scss'] +}) +export class FinanceComponent extends MyAppBase { + + contributions: Contribution[]; + summary: Contribution[]; + //#region Table Setting + contributionSettings = >{ + contextMenuItems: [ + // { + // id: 'add', + // enabled: true, + // title: 'Add New', + // icon: 'plus-circle-outline', + // callback: (datum, element) => { + // this.openEditingDialog(true); + // }, + // }, + // { + // id: 'edit', + // enabled: true, + // title: 'Edit', + // icon: 'edit', + // callback: (datum, element) => { + // this.openEditingDialog(false); + // }, + // }, + { + enabled: true, + id: 'delete', + title: 'Delete', + icon: 'trash-2-outline', + callback: (datum, element) => { + this.contributionService.delete(datum.id).pipe(first()).subscribe(result => { + + }); + }, + }], + onContextMenuOpening: (datum, menuItems) => { + menuItems.find(i => i.id == 'delete').visible = !!datum; + //menuItems.find(i => i.id == 'edit').visible = !!datum; + return datum; + }, + columns: [ + { + name: 'time', + title: 'Time', + type: 'date', + widthPx: 120, + //valuePrepareFunction: (item) => , + }, + { + name: 'contributor', + title: 'Contributor', + type: 'text', + widthPx: 150, + //valuePrepareFunction: (item) => , + }, + { + name: 'amount', + title: 'Amount', + type: 'text', + widthPx: 100, + class: 'text-right', + footerClass: 'text-right', + valuePrepareFunction: getAmountDisplay, + }, + { + name: 'comment', + title: 'Comment', + type: 'text', + widthPx: 200, + //valuePrepareFunction: (item) => , + }, + + ], + showFooter: true + }; + //#endregion + + constructor( + private contributionService: ContributionService, + private messageService: MsgBoxService, + private toastrService: NbToastrService, + private sessionService: SessionService, + private lineService: LineService, + private cdRef: ChangeDetectorRef, + private authService: AuthService, + private dlgService: NbDialogService, + protected stateService: StateService, + protected route: ActivatedRoute, + protected pastoralDomainService: PastoralDomainService + ) { + super(stateService, route, pastoralDomainService); + } + + pageOnInit(): void { + this.initializeData(); + } + + addContribution() { + this.dlgService.open(AddContributionDlgComponent, { + context: { + + } + }).onClose.pipe(first()).subscribe(result => { + if (result) { + result.groupId = this.currentDomain.id; + this.isLoading = true; + this.contributionService.createOrUpdate(result).pipe(first()).subscribe(result => { + this.refreshData(); + }); + } + }); + } + + private refreshData() { + this.isLoading = true; + this.pastoralDomainService.initialize().pipe(first()).subscribe(result => { + this.initializeData(); + }); + } + private initializeData() { + this.contributions = ObjectUtils.CloneValue(this.currentDomain.contributions); + this.summary = []; + + let totalComment = ''; + + let totalAmount = this.contributions.map(d => d.amount).reduce((a, b) => a + b, 0); + //Append Cost + if (this.currentDomain.happinessWeeks) { + + for (let i = 0; i < this.currentDomain.happinessWeeks.length; i++) { + const week = this.currentDomain.happinessWeeks[i]; + let weekCost = 0; + for (let j = 0; j < week.costs.length; j++) { + const weekCostItem = week.costs[j]; + this.contributions.push( + { + time: week.date, + contributor: `W${i + 1} - ${weekCostItem.tasker}`, + amount: -1 * weekCostItem.amount, + comment: weekCostItem.content + } as Contribution); + weekCost += weekCostItem.amount; + } + + if (weekCost > 0) { + + this.contributions.push( + { + time: week.date, + contributor: `${week.topic} - Sub Total`, + amount: 0, + comment: '$ ' + NumberUtils.FormatCurrency(weekCost) + } as Contribution); + } + } + let remainWeeks = this.currentDomain.happinessWeeks.filter(w => w.date >= new Date()).length; + + totalAmount = this.contributions.map(d => d.amount).reduce((a, b) => a + b, 0); + totalComment = StringUtils.getHtmlBadge(`剩餘每周(${remainWeeks}) 預算: $${NumberUtils.FormatCurrency(totalAmount / remainWeeks)}`, 'info'); + } + + + + this.summary.push( + { + time: null, + contributor: `Summary`, + amount: totalAmount, + comment: totalComment + } as Contribution); + this.isLoading = false; + + } +} +function getAmountDisplay(item: Contribution): string { + + if (item.amount != 0) { + return StringUtils.getHtmlBadge(NumberUtils.FormatCurrency(item.amount), item.amount > 0 ? 'success' : 'warning'); + } + + return "---------------"; +} + diff --git a/src/app/cell-group/happiness-group/happiness-group.component.scss b/src/app/cell-group/happiness-group/happiness-group.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/cell-group/happiness-group/happiness-group.component.ts b/src/app/cell-group/happiness-group/happiness-group.component.ts new file mode 100644 index 0000000..4cde347 --- /dev/null +++ b/src/app/cell-group/happiness-group/happiness-group.component.ts @@ -0,0 +1,48 @@ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { PastoralDomainService } from '../../services/crudServices/pastoral-domain.service'; +import { StateService } from '../../services/state.service'; +import { MyAppBase } from '../MyAppBase'; + + +@Component({ + selector: 'ngx-happiness-group', + template: ` + + `, + styleUrls: ['./happiness-group.component.scss'] +}) +export class BestListComponent extends MyAppBase { + + constructor( + protected stateService: StateService, + protected route: ActivatedRoute, + protected pastoralDomainService: PastoralDomainService + ) { + super(stateService, route, pastoralDomainService); + } + pageOnInit(): void { + this.stateService.SetPageTitle("Best"); + } +} + +@Component({ + selector: 'ngx-happiness-week-group', + template: ` + `, + styleUrls: ['./happiness-group.component.scss'] +}) +export class HappinessWeekListComponent extends MyAppBase { + + constructor( + protected stateService: StateService, + protected route: ActivatedRoute, + protected pastoralDomainService: PastoralDomainService + ) { + super(stateService, route, pastoralDomainService); + } + pageOnInit(): void { + this.stateService.SetPageTitle("Happiness Weeks"); + } +} + diff --git a/src/app/cell-group/join-domain/join-domain.component.html b/src/app/cell-group/join-domain/join-domain.component.html new file mode 100644 index 0000000..7636079 --- /dev/null +++ b/src/app/cell-group/join-domain/join-domain.component.html @@ -0,0 +1,17 @@ + + + 加入小組 + + +
+
+ + +
+
+
+ + + +
\ No newline at end of file diff --git a/src/app/cell-group/join-domain/join-domain.component.scss b/src/app/cell-group/join-domain/join-domain.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/cell-group/join-domain/join-domain.component.spec.ts b/src/app/cell-group/join-domain/join-domain.component.spec.ts new file mode 100644 index 0000000..30bc8be --- /dev/null +++ b/src/app/cell-group/join-domain/join-domain.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { JoinDomainComponent } from './join-domain.component'; + +describe('JoinDomainComponent', () => { + let component: JoinDomainComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ JoinDomainComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(JoinDomainComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/cell-group/join-domain/join-domain.component.ts b/src/app/cell-group/join-domain/join-domain.component.ts new file mode 100644 index 0000000..4701ce3 --- /dev/null +++ b/src/app/cell-group/join-domain/join-domain.component.ts @@ -0,0 +1,39 @@ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { DomainType, PastoralDomain } from '../../entity/PastoralDomain'; +import { PastoralDomainService } from '../../services/crudServices/pastoral-domain.service'; +import { StateService } from '../../services/state.service'; +import { MyAppBase } from '../MyAppBase'; +import { first } from 'rxjs/operators'; +import { DropDownOption } from '../../entity/dropDownOption'; + +@Component({ + selector: 'ngx-join-domain', + templateUrl: './join-domain.component.html', + styleUrls: ['./join-domain.component.scss'] +}) +export class JoinDomainComponent extends MyAppBase { + + constructor( + protected stateService: StateService, + protected route: ActivatedRoute, + protected pastoralDomainService: PastoralDomainService + ) { + super(stateService, route, pastoralDomainService); + this.redirectIfNoDomains = false; + } + domainId: string; + allDomains: PastoralDomain[]; + domainOptions: DropDownOption[] = []; + pageOnInit(): void { + this.isLoading = true; + this.pastoralDomainService.getAll().pipe(first()).subscribe(result => { + this.allDomains = result.filter(d => d.type == DomainType.CellGroup || d.type == DomainType.HappinessGroup); + this.domainOptions = this.allDomains.map(d => new DropDownOption(d.id, d.name)); + this.isLoading = false; + }); + } + joinDomain() { + + } +} \ No newline at end of file diff --git a/src/app/cell-group/prayer/prayer.component.ts b/src/app/cell-group/prayer/prayer.component.ts index c584916..56025bb 100644 --- a/src/app/cell-group/prayer/prayer.component.ts +++ b/src/app/cell-group/prayer/prayer.component.ts @@ -1,37 +1,38 @@ import { ChangeDetectorRef, Component, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; import { NbToastrService } from '@nebular/theme'; import { first } from 'rxjs/operators'; import { BindingHelper } from '../../entity/BindingHelper'; import { CellGroupRoutineEvents, CellGroupRoutineEventPrayer, CellGroupRoutineEventAttendee } from '../../entity/CellGroupRoutineEvents'; import { AuthService } from '../../services/auth.service'; import { CellGroupRoutineEventsService } from '../../services/crudServices/cell-group-routine-events.service'; +import { PastoralDomainService } from '../../services/crudServices/pastoral-domain.service'; import { HeaderService } from '../../services/header.service'; import { LineService } from '../../services/line.service'; import { MsgBoxService } from '../../services/msg-box.service'; import { SessionService } from '../../services/session.service'; +import { StateService } from '../../services/state.service'; import { DateUtils } from '../../utilities/date-utils'; import { NumberUtils } from '../../utilities/number-utils'; import { DinnerInfo } from '../dinner/dinner.component'; +import { MyAppBase } from '../MyAppBase'; @Component({ selector: 'ngx-prayer', templateUrl: './prayer.component.html', styleUrls: ['./prayer.component.scss'] }) -export class PrayerComponent implements OnInit { - - +export class PrayerComponent extends MyAppBase { constructor( private cellGroupRoutineEventsService: CellGroupRoutineEventsService, - private messageService: MsgBoxService, private toastrService: NbToastrService, - private sessionService: SessionService, - private lineService: LineService, private cdRef: ChangeDetectorRef, - private headerService: HeaderService, - private authService: AuthService + private authService: AuthService, + protected stateService: StateService, + protected route: ActivatedRoute, + protected pastoralDomainService: PastoralDomainService ) { - + super(stateService, route, pastoralDomainService); } cellGroupEvent: CellGroupRoutineEvents; @@ -42,8 +43,8 @@ export class PrayerComponent implements OnInit { isLoading: boolean = true; processing: boolean = false; - ngOnInit(): void { - this.headerService.setHeader("禱告中心") + pageOnInit(): void { + this.stateService.SetPageTitle("禱告中心"); this.getAllData(); } getAllData() { diff --git a/src/app/cell-group/user-profile/user-profile.component.html b/src/app/cell-group/user-profile/user-profile.component.html index 64e88c4..57cd7c3 100644 --- a/src/app/cell-group/user-profile/user-profile.component.html +++ b/src/app/cell-group/user-profile/user-profile.component.html @@ -5,20 +5,21 @@
-
+
-
+
-
+ +
@@ -27,25 +28,21 @@
-
-
- Married -
-
-
-
- Baptized -
-
-
+
+
+ + +
+
+
-
+
@@ -58,30 +55,30 @@ [(ngModel)]="data.avatarImage">
--> -
-
- - - + + +
+
+ Married
- -
-
- - - +
+
+ Baptized
- -
+
- - + + +
+
+
+
+ + +
@@ -89,10 +86,10 @@ - + --> + + + + +
+ + X {{treasure.unitAmount}} + +
+ +
+ +
+ + +
\ No newline at end of file diff --git a/src/app/games/massive-darkness2/massive-darkness2.component.scss b/src/app/games/massive-darkness2/massive-darkness2.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/games/massive-darkness2/massive-darkness2.component.spec.ts b/src/app/games/massive-darkness2/massive-darkness2.component.spec.ts new file mode 100644 index 0000000..11158f4 --- /dev/null +++ b/src/app/games/massive-darkness2/massive-darkness2.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MassiveDarkness2Component } from './massive-darkness2.component'; + +describe('MassiveDarkness2Component', () => { + let component: MassiveDarkness2Component; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ MassiveDarkness2Component ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(MassiveDarkness2Component); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/games/massive-darkness2/massive-darkness2.component.ts b/src/app/games/massive-darkness2/massive-darkness2.component.ts new file mode 100644 index 0000000..f5d5c1c --- /dev/null +++ b/src/app/games/massive-darkness2/massive-darkness2.component.ts @@ -0,0 +1,143 @@ +import { CommonModule } from '@angular/common'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core'; +import { FileService } from '../../services/file.service'; +import { MsgBoxService } from '../../services/msg-box.service'; +import { ArrayUtils } from '../../utilities/array-utils'; +import { ObjectUtils } from '../../utilities/object-utils'; + +@Component({ + selector: 'ngx-massive-darkness2', + templateUrl: './massive-darkness2.component.html', + styleUrls: ['./massive-darkness2.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class MassiveDarkness2Component implements OnInit { + TreasureType = TreasureType; + treasureBag: DrawingBag = new DrawingBag(); + + constructor( + private fileService: FileService, + private cdRef: ChangeDetectorRef, + private msgBoxService: MsgBoxService + ) { } + + ngOnInit(): void { + this.resetTreasureBag(); + this.detectChanges(); + } + detectChanges() { + + if (!this.cdRef['destroyed']) { + this.cdRef.detectChanges(); + } + } + resetTreasureBag() { + this.treasureBag.ClearAllItems(); + this.addTreasure(TreasureType.Common, 15); + } + addTreasure(type: TreasureType, amount: number = 1) { + let item = new DrawingItem(`${TreasureType[type]} Treasure`, `It's a ${TreasureType[type]} Treasure!`, this.fileService.ImageUrl(`TreasureToken/${TreasureType[type]}.png`), amount); + + this.treasureBag.AddItem(item); + this.detectChanges(); + } + treasureImage(type: TreasureType) { + return this.fileService.ImageUrl(`TreasureToken/${TreasureType[type]}.png`); + } + drawTreasure() { + + } +} +export enum TreasureType { + Common, + Rare, + Epic, + Legendary +} +export class DrawingBag { + constructor() { + this.drawingItems = []; + this.removedItems = []; + } + drawingItems: DrawingItem[] + removedItems: DrawingItem[] + + public Draw(amount: number): DrawingItem[] { + let drawItems: DrawingItem[] = []; + for (let i = 0; i < amount; i++) { + + drawItems.push(this.DrawAndRemove()); + } + this.RestoreRemoveItems(); + return drawItems; + } + public DrawAndRemove(): DrawingItem { + if (this.drawingItems.length > 0) { + let drawItem = null as DrawingItem; + let drawIndex = Math.random() * this.drawingItems.reduce((sum, current) => sum + current.unitAmount, 0); + + let drawCalc = 0; + for (let i = 0; i < this.drawingItems.length; i++) { + const item = this.drawingItems[i]; + drawCalc += item.unitAmount; + if (drawCalc >= drawIndex) { + drawItem = ObjectUtils.CloneValue(item); + drawItem.unitAmount = 1; + item.unitAmount -= 1; + break; + } + } + //ObjectUtils.CloneValue + this.RemoveItem(drawItem); + return drawItem; + } + return null; + } + + public RestoreRemoveItems() { + for (let i = 0; i < this.removedItems.length; i++) { + const removedItem = this.removedItems[i]; + this.AddItem(removedItem); + } + + } + public AddItem(item: DrawingItem) { + let existingItem = this.drawingItems.find(i => i.name == item.name); + if (existingItem) { + existingItem.unitAmount += item.unitAmount; + } else { + this.drawingItems.push(item); + } + } + + public RemoveItem(item: DrawingItem) { + let existingItem = this.removedItems.find(i => i.name == item.name); + if (existingItem) { + existingItem.unitAmount += item.unitAmount; + } else { + this.removedItems.push(item); + } + } + public ClearAllItems() { + + this.drawingItems = []; + this.removedItems = []; + } +} +export class DrawingItem { + constructor( + name: string, + description: string, + imageUrl: string, + unitAmount: number = 1 + ) { + this.imageUrl = imageUrl + this.name = name + this.description = description + this.unitAmount = unitAmount + } + imageUrl: string + name: string + description: string + unitAmount: number +} \ No newline at end of file diff --git a/src/app/happiness/best-list-dlg/best-editor-dlg/best-editor-dlg.component.html b/src/app/happiness/best-list-dlg/best-editor-dlg/best-editor-dlg.component.html new file mode 100644 index 0000000..7e129af --- /dev/null +++ b/src/app/happiness/best-list-dlg/best-editor-dlg/best-editor-dlg.component.html @@ -0,0 +1,42 @@ +
+ + + {{data.name}} + + + +
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+ +
+ +
+ + + + +
+
\ No newline at end of file diff --git a/src/app/happiness/best-list-dlg/best-editor-dlg/best-editor-dlg.component.scss b/src/app/happiness/best-list-dlg/best-editor-dlg/best-editor-dlg.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/happiness/best-list-dlg/best-editor-dlg/best-editor-dlg.component.spec.ts b/src/app/happiness/best-list-dlg/best-editor-dlg/best-editor-dlg.component.spec.ts new file mode 100644 index 0000000..b3ffdee --- /dev/null +++ b/src/app/happiness/best-list-dlg/best-editor-dlg/best-editor-dlg.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { BestEditorDlgComponent } from './best-editor-dlg.component'; + +describe('BestEditorDlgComponent', () => { + let component: BestEditorDlgComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ BestEditorDlgComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(BestEditorDlgComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/happiness/best-list-dlg/best-editor-dlg/best-editor-dlg.component.ts b/src/app/happiness/best-list-dlg/best-editor-dlg/best-editor-dlg.component.ts new file mode 100644 index 0000000..11fdd90 --- /dev/null +++ b/src/app/happiness/best-list-dlg/best-editor-dlg/best-editor-dlg.component.ts @@ -0,0 +1,45 @@ +import { Component, OnInit } from '@angular/core'; +import { NbDialogRef } from '@nebular/theme'; +import { first } from 'rxjs/operators'; +import { HappinessBEST } from '../../../entity/HappinessGroup'; +import { BestService } from '../../../services/crudServices/best.service'; + +@Component({ + selector: 'ngx-best-editor-dlg', + templateUrl: './best-editor-dlg.component.html', + styleUrls: ['./best-editor-dlg.component.scss'] +}) +export class BestEditorDlgComponent implements OnInit { + isAdding: boolean = false; + processing: boolean = false; + data: HappinessBEST; + constructor( + private bestService: BestService, + private dlgRef: NbDialogRef + ) { + + } + ngOnInit(): void { + if (this.isAdding) { + this.data = { id: 'new' } as HappinessBEST; + } + } + + close() { + this.dlgRef.close(); + } + update() { + if (this.processing == false) { + + this.processing = true; + + let func = this.bestService.update(this.data);//this.isAdding ? this.bestService.create(this.data) : + func.pipe(first()).subscribe(result => { + this.processing = false; + if (result) { + this.dlgRef.close(true); + } + }); + } + } +} diff --git a/src/app/admin/happiness-groups/best-list-dlg/best-list-dlg.component.html b/src/app/happiness/best-list-dlg/best-list-dlg.component.html similarity index 76% rename from src/app/admin/happiness-groups/best-list-dlg/best-list-dlg.component.html rename to src/app/happiness/best-list-dlg/best-list-dlg.component.html index ef1cffb..705d2f2 100644 --- a/src/app/admin/happiness-groups/best-list-dlg/best-list-dlg.component.html +++ b/src/app/happiness/best-list-dlg/best-list-dlg.component.html @@ -1,10 +1,13 @@ - + - Happiness Group:{{group.name}} Best List + {{group.name}} Best List - + + + @@ -24,8 +27,8 @@ (click)="openEditDlg(best)">Edit - +
diff --git a/src/app/happiness/best-list-dlg/best-list-dlg.component.scss b/src/app/happiness/best-list-dlg/best-list-dlg.component.scss new file mode 100644 index 0000000..6b59453 --- /dev/null +++ b/src/app/happiness/best-list-dlg/best-list-dlg.component.scss @@ -0,0 +1,7 @@ +nb-card { + max-height: 74vh; + .isDlg{ + max-height: 90vh; + width: 700px; + } +} \ No newline at end of file diff --git a/src/app/admin/happiness-groups/best-list-dlg/best-list-dlg.component.spec.ts b/src/app/happiness/best-list-dlg/best-list-dlg.component.spec.ts similarity index 100% rename from src/app/admin/happiness-groups/best-list-dlg/best-list-dlg.component.spec.ts rename to src/app/happiness/best-list-dlg/best-list-dlg.component.spec.ts diff --git a/src/app/happiness/best-list-dlg/best-list-dlg.component.ts b/src/app/happiness/best-list-dlg/best-list-dlg.component.ts new file mode 100644 index 0000000..cc3b66e --- /dev/null +++ b/src/app/happiness/best-list-dlg/best-list-dlg.component.ts @@ -0,0 +1,108 @@ +import { Component, Input, OnInit, Optional } from '@angular/core'; +import { NbDialogRef, NbDialogService, NbToastrService } from '@nebular/theme'; +import { first } from 'rxjs/operators'; +import { environment } from '../../../environments/environment'; +import { HappinessBEST } from '../../entity/HappinessGroup'; +import { PastoralDomain } from '../../entity/PastoralDomain'; +import { BestService } from '../../services/crudServices/best.service'; +import { HappinessGroupService } from '../../services/crudServices/happiness-group.service'; +import { LineService, LineGroup } from '../../services/line.service'; +import { MsgBoxService } from '../../services/msg-box.service'; +import { ADButtons, ADIcon } from '../../ui/alert-dlg/alert-dlg.model'; +import { ObjectUtils } from '../../utilities/object-utils'; +import { BestEditorDlgComponent } from './best-editor-dlg/best-editor-dlg.component'; + + +@Component({ + selector: 'best-list', + templateUrl: './best-list-dlg.component.html', + styleUrls: ['./best-list-dlg.component.scss'] +}) +export class BestListDlgComponent implements OnInit { + + processing: boolean = false; + isAdding: boolean = false; + @Input() group: PastoralDomain; + datum: HappinessBEST; + public get isDlg(): boolean { + return this.dlgRef != null; + } + constructor( + private msgBpxService: MsgBoxService, + private happinessGroupService: HappinessGroupService, + private toastrService: NbToastrService, + private bestService: BestService, + private lineService: LineService, + private dlgService: NbDialogService, + @Optional() private dlgRef: NbDialogRef, + ) { } + + ngOnInit(): void { + this.group.bests = this.group.bests.sort((a, b) => 0 - (a.name < b.name ? 1 : -1)); + } + + close() { + this.dlgRef.close(); + } + addBest() { + this.msgBpxService.showInputbox('Add Best', 'Please input Best\'s Name').pipe(first()).subscribe(result => { + if (result) { + let obj = { groupId: this.group.id, id: '', name: result } as HappinessBEST; + this.bestService.createOrUpdate(obj).pipe(first()).subscribe(result => { + this.group.bests.push(result); + }); + } + }); + } + + copyBestUrl(best: HappinessBEST) { + + var dummy = document.createElement("textarea"); + document.body.appendChild(dummy); + dummy.value = `${environment.invitationUrl}${best.id}`; + dummy.select(); + document.execCommand("copy"); + document.body.removeChild(dummy); + this.toastrService.success(dummy.value, "複製地址至剪貼簿!"); + } + copyBestList() { + let list = "".concat(...this.group.bests.map(b => `${b.name}\t\t: ${environment.invitationUrl}${b.id}\r\n`)); + var dummy = document.createElement("textarea"); + document.body.appendChild(dummy); + dummy.value = list; + dummy.select(); + document.execCommand("copy"); + document.body.removeChild(dummy); + this.toastrService.success(dummy.value, "複製地址至剪貼簿!"); + + //this.lineService.pushLineMessage(LineGroup.Chris, list); + + } + pushListToLine() { + this.msgBpxService.show('Push Whole List To Line', { text: 'Are You Sure?', icon: ADIcon.QUESTION, buttons: ADButtons.YesNo }).pipe(first()).subscribe(result => { + if (result) { + this.lineService.pushCommandMessage(this.group.id, 'BEST'); + this.toastrService.success('Sent', "Sent To Line"); + } + }); + } + openEditDlg(best: HappinessBEST) { + let isAdding = false; + this.dlgService.open(BestEditorDlgComponent, { + context: { + data: isAdding ? null : ObjectUtils.CloneValue(best), + isAdding: isAdding + } + }).onClose.pipe(first()).subscribe(result => { + if (result) { + ObjectUtils.CopyValue(result, best); + } + }); + + } + downloadBestQRCode(best: HappinessBEST) { + + this.happinessGroupService.getBestQrCode(best.name + ".png", best.id); + } + +} diff --git a/src/app/admin/happiness-groups/happiness-week-editor/happiness-week-editor.component.html b/src/app/happiness/happiness-week-editor/happiness-week-editor.component.html similarity index 100% rename from src/app/admin/happiness-groups/happiness-week-editor/happiness-week-editor.component.html rename to src/app/happiness/happiness-week-editor/happiness-week-editor.component.html diff --git a/src/app/admin/happiness-groups/happiness-week-editor/happiness-week-editor.component.scss b/src/app/happiness/happiness-week-editor/happiness-week-editor.component.scss similarity index 100% rename from src/app/admin/happiness-groups/happiness-week-editor/happiness-week-editor.component.scss rename to src/app/happiness/happiness-week-editor/happiness-week-editor.component.scss diff --git a/src/app/admin/happiness-groups/happiness-week-editor/happiness-week-editor.component.spec.ts b/src/app/happiness/happiness-week-editor/happiness-week-editor.component.spec.ts similarity index 100% rename from src/app/admin/happiness-groups/happiness-week-editor/happiness-week-editor.component.spec.ts rename to src/app/happiness/happiness-week-editor/happiness-week-editor.component.spec.ts diff --git a/src/app/admin/happiness-groups/happiness-week-editor/happiness-week-editor.component.ts b/src/app/happiness/happiness-week-editor/happiness-week-editor.component.ts similarity index 84% rename from src/app/admin/happiness-groups/happiness-week-editor/happiness-week-editor.component.ts rename to src/app/happiness/happiness-week-editor/happiness-week-editor.component.ts index a8a2920..5a04090 100644 --- a/src/app/admin/happiness-groups/happiness-week-editor/happiness-week-editor.component.ts +++ b/src/app/happiness/happiness-week-editor/happiness-week-editor.component.ts @@ -1,9 +1,8 @@ import { Component, OnInit } from '@angular/core'; import { NbDialogRef } from '@nebular/theme'; import { first } from 'rxjs/operators'; -import { HappinessWeek } from '../../../entity/HappinessGroup'; -import { HappinessGroupService } from '../../../services/crudServices/happiness-group.service'; - +import { HappinessWeek } from '../../entity/HappinessGroup'; +import { HappinessGroupService } from '../../services/crudServices/happiness-group.service'; @Component({ selector: 'ngx-happiness-week-editor', templateUrl: './happiness-week-editor.component.html', @@ -13,6 +12,7 @@ export class HappinessWeekEditorComponent implements OnInit { isAdding: boolean = false; processing: boolean = false; data: HappinessWeek; + allWeeks: HappinessWeek[]; constructor( private happinessGroupService: HappinessGroupService, private dlgRef: NbDialogRef diff --git a/src/app/admin/happiness-groups/happiness-week-list-dlg/happiness-week-list-dlg.component.html b/src/app/happiness/happiness-week-list-dlg/happiness-week-list-dlg.component.html similarity index 52% rename from src/app/admin/happiness-groups/happiness-week-list-dlg/happiness-week-list-dlg.component.html rename to src/app/happiness/happiness-week-list-dlg/happiness-week-list-dlg.component.html index 8e27224..1b6e31a 100644 --- a/src/app/admin/happiness-groups/happiness-week-list-dlg/happiness-week-list-dlg.component.html +++ b/src/app/happiness/happiness-week-list-dlg/happiness-week-list-dlg.component.html @@ -1,25 +1,30 @@ - + - Happiness Group:{{group.name}} Weeks List + {{group.name}} 幸福周 + -
+
- {{weekDisplay(week.seq)}} +

+
-
+
+ (click)="openTaskDlg(week,false)">Tasks +
@@ -30,6 +35,7 @@ - + \ No newline at end of file diff --git a/src/app/happiness/happiness-week-list-dlg/happiness-week-list-dlg.component.scss b/src/app/happiness/happiness-week-list-dlg/happiness-week-list-dlg.component.scss new file mode 100644 index 0000000..17415c3 --- /dev/null +++ b/src/app/happiness/happiness-week-list-dlg/happiness-week-list-dlg.component.scss @@ -0,0 +1,9 @@ +nb-card { + max-height: 74vh; + width: 615px; + max-width: 100vw; + .isDlg { + max-height: 90vh; + width: 700px; + } +} diff --git a/src/app/admin/happiness-groups/happiness-week-list-dlg/happiness-week-list-dlg.component.spec.ts b/src/app/happiness/happiness-week-list-dlg/happiness-week-list-dlg.component.spec.ts similarity index 100% rename from src/app/admin/happiness-groups/happiness-week-list-dlg/happiness-week-list-dlg.component.spec.ts rename to src/app/happiness/happiness-week-list-dlg/happiness-week-list-dlg.component.spec.ts diff --git a/src/app/happiness/happiness-week-list-dlg/happiness-week-list-dlg.component.ts b/src/app/happiness/happiness-week-list-dlg/happiness-week-list-dlg.component.ts new file mode 100644 index 0000000..cf1913d --- /dev/null +++ b/src/app/happiness/happiness-week-list-dlg/happiness-week-list-dlg.component.ts @@ -0,0 +1,100 @@ +import { Component, Input, OnInit, Optional } from '@angular/core'; +import { NbDialogRef, NbDialogService } from '@nebular/theme'; +import { first } from 'rxjs/operators'; +import { HappinessWeek } from '../../entity/HappinessGroup'; +import { PastoralDomain } from '../../entity/PastoralDomain'; +import { PastoralDomainService } from '../../services/crudServices/pastoral-domain.service'; +import { NumberUtils } from '../../utilities/number-utils'; +import { StringUtils } from '../../utilities/string-utils'; +import { HappinessWeekEditorComponent } from '../happiness-week-editor/happiness-week-editor.component'; +import { WeekTaskEditorComponent } from '../week-task-editor/week-task-editor.component'; + +@Component({ + selector: 'happiness-week-list', + templateUrl: './happiness-week-list-dlg.component.html', + styleUrls: ['./happiness-week-list-dlg.component.scss'] +}) +export class HappinessWeekListDlgComponent implements OnInit { + + processing: boolean = false; + + private _group: PastoralDomain; + public get group(): PastoralDomain { + return this._group; + } + @Input() public set group(v: PastoralDomain) { + if (this._group != v) { + this._group = v; + this.currentWeek = this.group.happinessWeeks.find(w => w.date >= new Date()); + } + } + currentWeek: HappinessWeek + public get isDlg(): boolean { + return this.dlgRef != null; + } + + constructor( + private dlgService: NbDialogService, + private pastoralDomainService: PastoralDomainService, + @Optional() private dlgRef: NbDialogRef + ) { } + + ngOnInit(): void { + } + close() { + this.dlgRef.close(); + } + openEditDlg(week: HappinessWeek) { + this.dlgService.open(HappinessWeekEditorComponent, { + context: { + data: week, + allWeeks: this.group.happinessWeeks + } + }).onClose.pipe(first()).subscribe(result => { + if (result) { + if (this.isDlg) { + this.close(); + } else { + this.runGetAllData(); + } + } + if (result) this.close(); + }); + } + openTaskDlg(week: HappinessWeek, showingCost: boolean) { + this.dlgService.open(WeekTaskEditorComponent, { + context: { + data: week, + showingCost: showingCost, + allData: this.group.happinessWeeks + } + }).onClose.pipe(first()).subscribe(result => { + if (result) { + if (this.isDlg) { + this.close(); + } else { + this.runGetAllData(); + } + } + }); + + } + + runGetAllData() { + + this.processing = true; + this.pastoralDomainService.initialize().pipe(first()).subscribe(result => { + this.group = this.pastoralDomainService.myHappinessGroup; + this.processing = false; + }); + } + weekDisplay(seq: number) { + let week = this.group.happinessWeeks[seq - 1]; + let title = `W${seq} ${week.topic}`; + let weekCost = week.costs.map(d => d.amount).reduce((a, b) => a + b, 0); + if (weekCost > 0) { + title += "\t" + StringUtils.getHtmlBadge(`Cost: $${NumberUtils.FormatCurrency(weekCost)}`, 'warning') + } + return title; + } +} diff --git a/src/app/happiness/happiness.module.ts b/src/app/happiness/happiness.module.ts new file mode 100644 index 0000000..bd3cf9c --- /dev/null +++ b/src/app/happiness/happiness.module.ts @@ -0,0 +1,68 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { NbMenuModule, NbInputModule, NbCardModule, NbButtonModule, NbActionsModule, NbCheckboxModule, NbRadioModule, NbDatepickerModule, NbSelectModule, NbIconModule, NbTagModule, NbStepperModule, NbListModule, NbUserModule, NbSpinnerModule, NbDialogModule, NbAlertModule } from '@nebular/theme'; +import { NgxMaskModule } from 'ngx-mask'; +import { ThemeModule } from '../@theme/theme.module'; +import { MaskDirectiveModule } from '../directives/mask-directive/mask-directive.module'; +import { AlertDlgModule } from '../ui/alert-dlg/alert-dlg.module'; +import { CurrencyInputModule } from '../ui/currency-input/currency-input.module'; +import { DateInputModule } from '../ui/date-input/date-input.module'; +import { DropDownListModule } from '../ui/drop-down-list/drop-down-list.module'; +import { FancyTableModule } from '../ui/fancy-table/fancy-table.module'; +import { WeekTaskEditorComponent } from './week-task-editor/week-task-editor.component'; +import { HappinessWeekEditorComponent } from './happiness-week-editor/happiness-week-editor.component'; +import { BestListDlgComponent } from './best-list-dlg/best-list-dlg.component'; +import { HappinessWeekListDlgComponent } from './happiness-week-list-dlg/happiness-week-list-dlg.component'; +import { BestEditorDlgComponent } from './best-list-dlg/best-editor-dlg/best-editor-dlg.component'; +import { LoadingSpinnerModule } from '../ui/loading-spinner/loading-spinner.module'; +import { AddNewCostDlgComponent } from './week-task-editor/add-new-cost-dlg/add-new-cost-dlg.component'; + + + +@NgModule({ + declarations: [ + WeekTaskEditorComponent, + HappinessWeekEditorComponent, + BestListDlgComponent, + HappinessWeekListDlgComponent, + BestEditorDlgComponent, + AddNewCostDlgComponent + ], + imports: [ + CommonModule, + FormsModule, + ThemeModule, + NbMenuModule, + NbInputModule, + NbCardModule, + NbButtonModule, + NbActionsModule, + NbCheckboxModule, + NbRadioModule, + NbDatepickerModule, + NbSelectModule, + NbIconModule, + NbTagModule, + NbStepperModule, + NbListModule, + NbUserModule, + NbSpinnerModule, + NbDialogModule, + NbAlertModule, + NbSpinnerModule, + AlertDlgModule, + FancyTableModule, + DropDownListModule, + NgxMaskModule, + CurrencyInputModule, + MaskDirectiveModule, + DateInputModule, + LoadingSpinnerModule + ], + exports: [ + BestListDlgComponent, + HappinessWeekListDlgComponent + ] +}) +export class HappinessModule { } diff --git a/src/app/happiness/week-task-editor/add-new-cost-dlg/add-new-cost-dlg.component.html b/src/app/happiness/week-task-editor/add-new-cost-dlg/add-new-cost-dlg.component.html new file mode 100644 index 0000000..47b6a6c --- /dev/null +++ b/src/app/happiness/week-task-editor/add-new-cost-dlg/add-new-cost-dlg.component.html @@ -0,0 +1,34 @@ + + + 新增開銷 + + +
+ +
+
+ + + +
+
+ +
+
+ + +
+
+
+
+ + +
+
+
+
+ + + + +
\ No newline at end of file diff --git a/src/app/happiness/week-task-editor/add-new-cost-dlg/add-new-cost-dlg.component.scss b/src/app/happiness/week-task-editor/add-new-cost-dlg/add-new-cost-dlg.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/happiness/week-task-editor/add-new-cost-dlg/add-new-cost-dlg.component.spec.ts b/src/app/happiness/week-task-editor/add-new-cost-dlg/add-new-cost-dlg.component.spec.ts new file mode 100644 index 0000000..ba41835 --- /dev/null +++ b/src/app/happiness/week-task-editor/add-new-cost-dlg/add-new-cost-dlg.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AddNewCostDlgComponent } from './add-new-cost-dlg.component'; + +describe('AddNewCostDlgComponent', () => { + let component: AddNewCostDlgComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AddNewCostDlgComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AddNewCostDlgComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/happiness/week-task-editor/add-new-cost-dlg/add-new-cost-dlg.component.ts b/src/app/happiness/week-task-editor/add-new-cost-dlg/add-new-cost-dlg.component.ts new file mode 100644 index 0000000..aefdf0a --- /dev/null +++ b/src/app/happiness/week-task-editor/add-new-cost-dlg/add-new-cost-dlg.component.ts @@ -0,0 +1,32 @@ +import { Component, OnInit } from '@angular/core'; +import { NbDialogRef } from '@nebular/theme'; +import { DropDownOption } from '../../../entity/dropDownOption'; +import { HappinessCost } from '../../../entity/happiness-cost.model'; +import { AuthService } from '../../../services/auth.service'; + +@Component({ + selector: 'ngx-add-new-cost-dlg', + templateUrl: './add-new-cost-dlg.component.html', + styleUrls: ['./add-new-cost-dlg.component.scss'] +}) +export class AddNewCostDlgComponent implements OnInit { + taskrOptions: DropDownOption[] = []; + task: HappinessCost; + constructor( + private authService: AuthService, + private dlgRef: NbDialogRef + ) { } + + ngOnInit(): void { + this.task = new HappinessCost(); + this.task.tasker = this.authService.userAccess.firstName; + } + close() { + this.dlgRef.close(); + } + submit() { + if (this.task.tasker && this.task.content && this.task.amount > 0) { + this.dlgRef.close(this.task); + } + } +} diff --git a/src/app/happiness/week-task-editor/week-task-editor.component.html b/src/app/happiness/week-task-editor/week-task-editor.component.html new file mode 100644 index 0000000..9de4e91 --- /dev/null +++ b/src/app/happiness/week-task-editor/week-task-editor.component.html @@ -0,0 +1,121 @@ +
+ + + + + + 第 {{data.seq}} 周 {{data.topic}} 分工 + + + + +
+
+
+ + + +
+
+ +
+
+ + +
+
+
+ +
+ + + + + + +
+
+ + + + 第 {{data.seq}} 周 {{data.topic}} 開銷 + + + + + + +
+
+
+ + + +
+
+ +
+
+ + +
+
+
+
+ + +
+
+
+ + + 本周暫無開銷 + + +
+ + + + + + + +
+
+
+ +
\ No newline at end of file diff --git a/src/app/happiness/week-task-editor/week-task-editor.component.scss b/src/app/happiness/week-task-editor/week-task-editor.component.scss new file mode 100644 index 0000000..e4a5b3b --- /dev/null +++ b/src/app/happiness/week-task-editor/week-task-editor.component.scss @@ -0,0 +1,3 @@ +nb-flip-card{ + max-width: 88vw; +} \ No newline at end of file diff --git a/src/app/admin/happiness-groups/week-task-editor/week-task-editor.component.spec.ts b/src/app/happiness/week-task-editor/week-task-editor.component.spec.ts similarity index 100% rename from src/app/admin/happiness-groups/week-task-editor/week-task-editor.component.spec.ts rename to src/app/happiness/week-task-editor/week-task-editor.component.spec.ts diff --git a/src/app/happiness/week-task-editor/week-task-editor.component.ts b/src/app/happiness/week-task-editor/week-task-editor.component.ts new file mode 100644 index 0000000..541d8e8 --- /dev/null +++ b/src/app/happiness/week-task-editor/week-task-editor.component.ts @@ -0,0 +1,129 @@ +import { ChangeDetectorRef, Component, OnInit } from '@angular/core'; +import { NbDialogRef, NbDialogService, NbToastrService } from '@nebular/theme'; +import { first } from 'rxjs/operators'; +import { DropDownOption } from '../../entity/dropDownOption'; +import { HappinessCost } from '../../entity/happiness-cost.model'; +import { HappinessWeek, HappinessTaskType, HappinessTask } from '../../entity/HappinessGroup'; +import { HappinessCostService } from '../../services/crudServices/happiness-cost.service'; +import { HappinessTaskService } from '../../services/crudServices/happiness-group.service'; +import { StringUtils } from '../../utilities/string-utils'; +import { AddNewCostDlgComponent } from './add-new-cost-dlg/add-new-cost-dlg.component'; + +@Component({ + selector: 'ngx-week-task-editor', + templateUrl: './week-task-editor.component.html', + styleUrls: ['./week-task-editor.component.scss'] +}) +export class WeekTaskEditorComponent implements OnInit { + processing: boolean = false; + allData: HappinessWeek[]; + data: HappinessWeek; + taskrOptions: DropDownOption[] = []; + showingCost: boolean = false; + constructor( + private happinessTaskService: HappinessTaskService, + private happinessCostService: HappinessCostService, + private dlgRef: NbDialogRef, + private dlgService: NbDialogService, + private toastrService: NbToastrService, + private cdRef: ChangeDetectorRef + ) { + + } + ngOnInit(): void { + if (this.data.tasks.length == 0) { + this.data.tasks = []; + for (let i = HappinessTaskType.IceBreak; i <= HappinessTaskType.Dessert; i++) { + this.data.tasks.push( + { + weekId: this.data.id, + id: 'new', + type: i as HappinessTaskType, + tasker: '', + content: '' + } as HappinessTask + + ) + } + } + let names = [] as string[]; + this.allData.forEach(week => { + if (week.tasks) { + names = names.concat(week.tasks.map(t => t.tasker ? t.tasker.trim() : '')); + + } + }); + this.taskrOptions = names.filter(function (item, pos) { + return !StringUtils.isNullOrWhitespace(item) && names.indexOf(item) == pos; + }).map(name => new DropDownOption(name, name)); + } + + close() { + this.dlgRef.close(); + } + update() { + if (this.processing == false) { + + this.processing = true; + + this.happinessTaskService.createOrUpdateAll(this.data.tasks).pipe(first()).subscribe(result => { + this.processing = false; + this.toastrService.success("Update Success!"); + }); + } + } + + updateCost() { + if (this.processing == false) { + + this.processing = true; + + this.happinessCostService.createOrUpdateAll(this.data.costs).pipe(first()).subscribe(result => { + this.processing = false; + this.toastrService.success("Update Cost Success!"); + }); + } + + } + getTaskTitle(t: HappinessTaskType) { + switch (t) { + case HappinessTaskType.IceBreak: return '帶遊戲'; + case HappinessTaskType.Worship: return '唱歌'; + case HappinessTaskType.Testimony: return '見證'; + case HappinessTaskType.Message: return '信息'; + case HappinessTaskType.Gift: return '準備禮物'; + case HappinessTaskType.Dessert: return '準備點心'; + default: break; + } + } + + toggleView() { + this.showingCost = !this.showingCost; + } + addNewCost() { + this.dlgService.open(AddNewCostDlgComponent, { + context: { + taskrOptions: this.taskrOptions + } + }).onClose.pipe(first()).subscribe(result => { + if (result) { + result.weekId = this.data.id; + this.happinessCostService.createOrUpdate(result).pipe(first()).subscribe(result => { + this.data.costs.push(result); + }); + } + }); + } + gotoNextWeek() { + if ((this.allData.indexOf(this.data) + 1) < this.allData.length) { + this.data = this.allData[this.allData.indexOf(this.data) + 1]; + this.cdRef.detectChanges(); + } + } + gotoPreviousWeek() { + if ((this.allData.indexOf(this.data) - 1) >= 0) { + this.data = this.allData[this.allData.indexOf(this.data) - 1]; + this.cdRef.detectChanges(); + } + } +} \ No newline at end of file diff --git a/src/app/home/header/header.component.html b/src/app/home/header/header.component.html index 2481bad..5cfa114 100644 --- a/src/app/home/header/header.component.html +++ b/src/app/home/header/header.component.html @@ -5,7 +5,7 @@ data-header-fix-moment-classes="light-theme u-theme-shadow-v1 g-bg-white g-py-5--md">