Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement quest-selector #546

Merged
merged 1 commit into from Mar 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -218,6 +218,11 @@
</div>
<div class="form-group col-12 col-sm-6 col-md-4 col-lg-3 col-xl-2">
<label class="control-label" for="startquest">startquest</label>
<keira-quest-selector-btn
[control]="editorService.form.controls.startquest"
[config]="{ name: 'startquest' }"
[modalClass]="'modal-lg'"
></keira-quest-selector-btn>
<i
class="fas fa-info-circle ml-1" [placement]="'auto'"
[tooltip]="'The ID of the quest that this item will start if right-clicked. See quest_template.id'"
Expand Down
2 changes: 2 additions & 0 deletions src/app/features/item/item-template/item-template.module.ts
Expand Up @@ -19,6 +19,7 @@ import { ItemEnchantmentSelectorModule } from '@keira-shared/modules/selectors/i
import { HolidaySelectorModule } from '@keira-shared/modules/selectors/holiday-selector/holiday-selector.module';
import { LanguageSelectorModule } from '@keira-shared/modules/selectors/language-selector/language-selector.module';
import { ItemLimitCategorySelectorModule } from '@keira-shared/modules/selectors/item-limit-category-selector/item-limit-category-selector.module';
import { QuestSelectorModule } from '@keira-shared/modules/selectors/quest-selector/quest-selector.module';

@NgModule({
declarations: [
Expand All @@ -41,6 +42,7 @@ import { ItemLimitCategorySelectorModule } from '@keira-shared/modules/selectors
HolidaySelectorModule,
LanguageSelectorModule,
ItemLimitCategorySelectorModule,
QuestSelectorModule,
],
exports: [
ItemTemplateComponent,
Expand Down
Expand Up @@ -35,6 +35,11 @@

<div class="form-group col-12 col-sm-6 col-md-4 col-lg-3 col-xl-2">
<label class="control-label" for="PrevQuestID">PrevQuestID</label>
<keira-quest-selector-btn
[control]="editorService.form.controls.PrevQuestID"
[config]="{ name: 'PrevQuestID' }"
[modalClass]="'modal-lg'"
></keira-quest-selector-btn>
<i
class="fas fa-info-circle ml-1" [placement]="'auto'"
[tooltip]="'if > 0: previous quest id; if < 0 parent quest id'"
Expand All @@ -44,6 +49,11 @@

<div class="form-group col-12 col-sm-6 col-md-4 col-lg-3 col-xl-2">
<label class="control-label" for="NextQuestID">NextQuestID</label>
<keira-quest-selector-btn
[control]="editorService.form.controls.NextQuestID"
[config]="{ name: 'NextQuestID' }"
[modalClass]="'modal-lg'"
></keira-quest-selector-btn>
<i
class="fas fa-info-circle ml-1" [placement]="'auto'"
[tooltip]="'Contains the next quest id, in case PrevQuestId of that other quest is not sufficient.'"
Expand Down
Expand Up @@ -230,5 +230,36 @@ describe('QuestTemplateAddon integration tests', () => {
);
});

it('changing a value via QuestSelector should correctly work', async () => {
const field = 'NextQuestID';
const mysqlQueryService = TestBed.inject(MysqlQueryService);
(mysqlQueryService.query as Spy).and.returnValue(of(
[{ ID: 123, LogTitle: 'Mock Quest' }]
));

page.clickElement(page.getSelectorBtn(field));
await page.whenReady();
page.expectModalDisplayed();

page.clickSearchBtn();

await fixture.whenStable();
page.clickRowOfDatatableInModal(0);
await page.whenReady();
page.clickModalSelect();
await page.whenReady();

page.expectDiffQueryToContain(
'UPDATE `quest_template_addon` SET `NextQuestID` = 123 WHERE (`ID` = 1234);'
);
page.expectFullQueryToContain(
'DELETE FROM `quest_template_addon` WHERE (`ID` = 1234);\n' +
'INSERT INTO `quest_template_addon` (`ID`, `MaxLevel`, `AllowableClasses`, `SourceSpellID`, `PrevQuestID`, `NextQuestID`, ' +
'`ExclusiveGroup`, `RewardMailTemplateID`, `RewardMailDelay`, `RequiredSkillID`, `RequiredSkillPoints`, `RequiredMinRepFaction`, ' +
'`RequiredMaxRepFaction`, `RequiredMinRepValue`, `RequiredMaxRepValue`, `ProvidedItemCount`, `SpecialFlags`) VALUES\n' +
'(1234, 1, 2, 3, 4, 123, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0);'
);
});

});
});
Expand Up @@ -14,6 +14,7 @@ import { QuestTemplateAddonService } from './quest-template-addon.service';
import { SpellSelectorModule } from '@keira-shared/modules/selectors/spell-selector/spell-selector.module';
import { FactionSelectorModule } from '@keira-shared/modules/selectors/faction-selector/faction-selector.module';
import { SkillSelectorModule } from '@keira-shared/modules/selectors/skill-selector/skill-selector.module';
import { QuestSelectorModule } from '@keira-shared/modules/selectors/quest-selector/quest-selector.module';

@NgModule({
declarations: [
Expand All @@ -31,6 +32,7 @@ import { SkillSelectorModule } from '@keira-shared/modules/selectors/skill-selec
SpellSelectorModule,
FactionSelectorModule,
SkillSelectorModule,
QuestSelectorModule,
],
exports: [
QuestTemplateAddonComponent,
Expand Down
19 changes: 19 additions & 0 deletions src/app/shared/modules/search/quest-search.service.spec.ts
@@ -0,0 +1,19 @@
import { TestBed } from '@angular/core/testing';
import { instance } from 'ts-mockito';

import { QuestSearchService } from './quest-search.service';
import { MockedSqliteQueryService } from '../../testing/mocks';
import { SqliteQueryService } from '@keira-shared/services/sqlite-query.service';

describe('QuestSearchService', () => {
beforeEach(() => TestBed.configureTestingModule({
providers: [
{ provide: SqliteQueryService, useValue: instance(MockedSqliteQueryService) },
]
}));

it('should be created', () => {
const service: QuestSearchService = TestBed.inject(QuestSearchService);
expect(service).toBeTruthy();
});
});
22 changes: 22 additions & 0 deletions src/app/shared/modules/search/quest-search.service.ts
@@ -0,0 +1,22 @@
import { Injectable } from '@angular/core';

import { SearchService } from './search.service';
import { MysqlQueryService } from '@keira-shared/services/mysql-query.service';
import {
QUEST_TEMPLATE_SEARCH_FIELDS,
QUEST_TEMPLATE_TABLE,
QuestTemplate,
} from '../../types/quest-template.type';

@Injectable({
providedIn: 'root'
})
export class QuestSearchService extends SearchService<QuestTemplate> {

/* istanbul ignore next */ // because of: https://github.com/gotwarlost/istanbul/issues/690
constructor(
protected queryService: MysqlQueryService,
) {
super(queryService, QUEST_TEMPLATE_TABLE, QUEST_TEMPLATE_SEARCH_FIELDS);
}
}
@@ -0,0 +1,26 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { QuestSelectorBtnComponent } from './quest-selector-btn.component';
import { QuestSelectorModule } from './quest-selector.module';

describe('QuestSelectorBtnComponent', () => {
let component: QuestSelectorBtnComponent;
let fixture: ComponentFixture<QuestSelectorBtnComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [ QuestSelectorModule ],
})
.compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(QuestSelectorBtnComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,23 @@
import { Component } from '@angular/core';
import { BsModalService } from 'ngx-bootstrap';

import { QuestSelectorModalComponent } from './quest-selector-modal.component';
import { BaseSelectorBtnComponent } from '../base-selector/base-selector-btn.component';

@Component({
selector: 'keira-quest-selector-btn',
templateUrl: '../base-selector/base-selector-btn.component.html',
styleUrls: ['../base-selector/base-selector-btn.component.scss']
})
export class QuestSelectorBtnComponent extends BaseSelectorBtnComponent {

/* istanbul ignore next */ // because of: https://github.com/gotwarlost/istanbul/issues/690
constructor(
modalService: BsModalService,
) {
super(
QuestSelectorModalComponent,
modalService,
);
}
}
@@ -0,0 +1,57 @@
<div class="modal-body">

<p class="lead text-center mb-1">Quest selector</p>

<form [formGroup]="searchService.queryForm">
<div class="row">
<ng-container [formGroup]="searchService.fields">
<div class="form-group col-3">
<input [formControlName]="'ID'" type="number" class="form-control form-control-sm" id="ID" placeholder="ID">
</div>
<div class="form-group col-5">
<input [formControlName]="'LogTitle'" class="form-control form-control-sm" id="LogTitle" placeholder="Name">
</div>
</ng-container>
<div class="form-group col-2">
<input [formControlName]="'limit'" class="form-control form-control-sm" id="limit" placeholder="Unlimited">
</div>
<div class="col-2">
<button
id="search-btn"
class="btn btn-primary btn-sm"
[disabled]="searchService.queryForm.invalid"
(click)="searchService.onSearch()"
>Search</button>
</div>
</div>
<code [highlight]="searchService.query"></code>
</form>

<div *ngIf="searchService.rows">

<ngx-datatable
class="bootstrap table table-striped text-center datatable-select highlight-select"
[rows]="searchService.rows"
[headerHeight]="DTCFG.headerHeight"
[footerHeight]="DTCFG.footerHeight"
[columnMode]="DTCFG.columnMode"
[rowHeight]="DTCFG.rowHeight"
[limit]="DTCFG.limit"
[selectionType]="DTCFG.selectionType"
(select)='onSelect($event)'
>
<ngx-datatable-column name="ID" prop="ID" [minWidth]="100">
<ng-template let-row="row" ngx-datatable-cell-template>
{{ row.ID }}
</ng-template>
</ngx-datatable-column>
<ngx-datatable-column name="Quest Title" prop="LogTitle"></ngx-datatable-column>
</ngx-datatable>

</div>
</div>

<div class="modal-footer">
<button type="button" class="btn btn-danger" id="modal-cancel-btn" (click)="onCancel()">Cancel</button>
<button type="button" class="btn btn-success" id="modal-select-btn" (click)="onSave()">Select</button>
</div>
@@ -0,0 +1,39 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { BsModalRef } from 'ngx-bootstrap';
import { instance } from 'ts-mockito';

import { QuestSelectorModalComponent } from './quest-selector-modal.component';
import { MysqlQueryService } from '../../../services/mysql-query.service';
import { MockedMysqlQueryService } from '@keira-testing/mocks';
import { QuestSearchService } from '../../search/quest-search.service';
import { QuestSelectorModule } from './quest-selector.module';

describe('QuestSelectorModalComponent', () => {
let component: QuestSelectorModalComponent;
let fixture: ComponentFixture<QuestSelectorModalComponent>;
let searchService: QuestSearchService;

beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [ QuestSelectorModule ],
providers: [
BsModalRef,
{ provide: MysqlQueryService, useValue: instance(MockedMysqlQueryService) },
],
})
.compileComponents();
}));

beforeEach(() => {
searchService = TestBed.inject(QuestSearchService);
searchService.query = '--mock query';

fixture = TestBed.createComponent(QuestSelectorModalComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,22 @@
import { Component, } from '@angular/core';
import { BsModalRef } from 'ngx-bootstrap';

import { QuestSearchService } from '../../search/quest-search.service';
import { QUEST_TEMPLATE_ID } from '@keira-types/quest-template.type';
import { SearchSelectorModalComponent } from '../base-selector/search-selector-modal.component';

@Component({
selector: 'keira-quest-selector-modal',
templateUrl: './quest-selector-modal.component.html',
styleUrls: ['./quest-selector-modal.component.scss']
})
export class QuestSelectorModalComponent extends SearchSelectorModalComponent {

/* istanbul ignore next */ // because of: https://github.com/gotwarlost/istanbul/issues/690
constructor(
protected bsModalRef: BsModalRef,
public searchService: QuestSearchService,
) {
super(QUEST_TEMPLATE_ID, bsModalRef);
}
}
@@ -0,0 +1,31 @@
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';

import { QuestSelectorModalComponent } from './quest-selector-modal.component';
import { QuestSelectorBtnComponent } from './quest-selector-btn.component';
import { highlightOptions } from '@keira-config/highlight.config';
import { HighlightModule } from 'ngx-highlightjs';
import { NgxDatatableModule } from '@swimlane/ngx-datatable';
import { ModalModule } from 'ngx-bootstrap';

@NgModule({
entryComponents: [
QuestSelectorModalComponent,
],
declarations: [
QuestSelectorBtnComponent,
QuestSelectorModalComponent,
],
imports: [
BrowserModule,
ReactiveFormsModule,
NgxDatatableModule,
ModalModule.forRoot(),
HighlightModule.forRoot(highlightOptions),
],
exports: [
QuestSelectorBtnComponent,
],
})
export class QuestSelectorModule {}