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

fix(backend): use new backend for orgdiagram for valid results #664

Merged
merged 7 commits into from
May 17, 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 32 additions & 8 deletions .azure/pipelines/Phonebook.preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ pr:
variables:
image_repo: tsystemsmms
image_namespace: phonebook-build
image_tag: pr-$(System.PullRequest.PullRequestNumber)
image_tag_frontend: pr-$(System.PullRequest.PullRequestNumber)
image_tag_source_peoplesoft: pr-$(System.PullRequest.PullRequestNumber)-peoplesoft
helm_artifact_name: HelmPhonebookPackage

jobs:
Expand All @@ -19,23 +20,46 @@ jobs:
inputs:
version: '12.x'

- script: node version.js $(image_tag) $(Build.SourceVersion) $(Build.SourceVersion)
- script: node version.js $(image_tag_frontend) $(Build.SourceVersion) $(Build.SourceVersion)
displayName: 'Write Version Number'
workingDirectory: 'Phonebook.Frontend/'

- script: docker build -t $(image_repo)/$(image_namespace):$(image_tag) .
- script: docker build -t $(image_repo)/$(image_namespace):$(image_tag_frontend) .
displayName: 'Build Image'
workingDirectory: 'Phonebook.Frontend/'

- script: |
docker login -u $DOCKER_REGISTRY_USER -p $DOCKER_REGISTRY_PASSWORD
docker push $(image_repo)/$(image_namespace):$(image_tag)
docker push $(image_repo)/$(image_namespace):$(image_tag_frontend)
workingDirectory: 'Phonebook.Frontend/'
displayName: 'Push Image'
env:
DOCKER_REGISTRY_PASSWORD: $(DOCKER_REGISTRY_PASSWORD)
DOCKER_REGISTRY_USER: $(DOCKER_REGISTRY_USER)

- job: build_phonebook_source_peoplesoft
displayName: 'Phonebook Source Peoplesoft'
pool:
vmImage: 'ubuntu-16.04'
steps:
- task: UseNode@1
inputs:
version: '12.x'


- script: docker build -t $(image_repo)/$(image_namespace):$(image_tag_source_peoplesoft) .
displayName: 'Build Image'
workingDirectory: 'Phonebook.Source.PeopleSoft/'

- script: |
docker login -u $DOCKER_REGISTRY_USER -p $DOCKER_REGISTRY_PASSWORD
docker push $(image_repo)/$(image_namespace):$(image_tag_source_peoplesoft)
workingDirectory: 'Phonebook.Source.PeopleSoft/'
displayName: 'Push Image'
env:
DOCKER_REGISTRY_PASSWORD: $(DOCKER_REGISTRY_PASSWORD)
DOCKER_REGISTRY_USER: $(DOCKER_REGISTRY_USER)

- job: build_phonebook_helm
displayName: Phonebook Helm Chart
pool:
Expand Down Expand Up @@ -63,7 +87,7 @@ jobs:
pool:
vmImage: 'ubuntu-16.04'
variables:
namespace: $(image_tag)
namespace: $(image_tag_frontend)
steps:
- download: current
artifact: $(helm_artifact_name)
Expand Down Expand Up @@ -98,7 +122,7 @@ jobs:
chartType: FilePath
chartPath: '$(Pipeline.Workspace)/$(helm_artifact_name)/phonebook-0.1.0.tgz'
releaseName: phonebook-$(namespace)
overrideValues: 'frontend.image.tag=$(image_tag),frontend.image.repository=$(image_repo),frontend.image.name=$(image_namespace),traefik.enabled=false,host=$(image_tag).demo-phonebook.me'
overrideValues: 'frontend.image.tag=$(image_tag_frontend),frontend.image.repository=$(image_repo),frontend.image.name=$(image_namespace),source.peoplesoft.image.tag=$(image_tag_source_peoplesoft),source.peoplesoft.image.name=$(image_namespace),traefik.enabled=false,host=$(image_tag_frontend).demo-phonebook.me'
valueFile: 'demo/values.yml'
recreate: true
tillerNamespace: kube-system
Expand Down Expand Up @@ -128,7 +152,7 @@ jobs:
}
body: |
{
"body": "Preview Environment ready at https://$(image_tag).demo-phonebook.me"
"body": "Preview Environment ready at https://$(image_tag_frontend).demo-phonebook.me"
}
urlSuffix: 'repos/T-Systems-MMS/phonebook/issues/$(System.PullRequest.PullRequestNumber)/comments'
waitForCompletion: 'false'
Expand All @@ -153,7 +177,7 @@ jobs:
pool:
vmImage: 'ubuntu-16.04'
variables:
namespace: $(image_tag)
namespace: $(image_tag_frontend)
steps:
- checkout: none
- task: HelmInstaller@1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const routes: Routes = [
{ path: ':first/:second/:third', component: OrganigramComponent },
{ path: ':first/:second/:third/:fourth', component: OrganigramComponent },
{ path: ':first/:second/:third/:fourth/:fifth', component: OrganigramComponent },
{ path: ':first/:second/:third/:fourth/:fifth/:sixth', component: OrganigramComponent },
];

@NgModule({
Expand Down
26 changes: 13 additions & 13 deletions Phonebook.Frontend/src/app/modules/table/table-logic.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ describe('Table Logic - Sort', () => {
false,
new Contacts('', '', '', '', new Messenger('', 0)),
new Location(new City('', ''), []),
new Business([], [], [], [], [], [], '')
new Business(null, [], [], [], [], [], [], '')
),
new Person(
PersonStatus.Interner_Mitarbeiter,
Expand All @@ -36,7 +36,7 @@ describe('Table Logic - Sort', () => {
false,
new Contacts('', '', '', '', new Messenger('', 0)),
new Location(new City('', ''), []),
new Business([], [], [], [], [], [], '')
new Business(null, [], [], [], [], [], [], '')
),
];
expect(
Expand All @@ -55,7 +55,7 @@ describe('Table Logic - Sort', () => {
false,
new Contacts('', '', '', '', new Messenger('', 0)),
new Location(new City('', ''), []),
new Business([], [], [], [], [], [], '')
new Business(null, [], [], [], [], [], [], '')
),
new Person(
PersonStatus.Interner_Mitarbeiter,
Expand All @@ -67,7 +67,7 @@ describe('Table Logic - Sort', () => {
false,
new Contacts('', '', '', '', new Messenger('', 0)),
new Location(new City('', ''), []),
new Business([], [], [], [], [], [], '')
new Business(null, [], [], [], [], [], [], '')
),
]);
});
Expand All @@ -83,7 +83,7 @@ describe('Table Logic - Sort', () => {
false,
new Contacts('', '', '', '', new Messenger('', 0)),
new Location(new City('', ''), []),
new Business([], [], [], [], [], [], '')
new Business(null, [], [], [], [], [], [], '')
),
new Person(
PersonStatus.Interner_Mitarbeiter,
Expand All @@ -95,7 +95,7 @@ describe('Table Logic - Sort', () => {
false,
new Contacts('', '', '', '', new Messenger('', 0)),
new Location(new City('', ''), []),
new Business([], [], [], [], [], [], '')
new Business(null, [], [], [], [], [], [], '')
),
];

Expand All @@ -115,7 +115,7 @@ describe('Table Logic - Sort', () => {
false,
new Contacts('', '', '', '', new Messenger('', 0)),
new Location(new City('', ''), []),
new Business([], [], [], [], [], [], '')
new Business(null, [], [], [], [], [], [], '')
),
new Person(
PersonStatus.Interner_Mitarbeiter,
Expand All @@ -127,7 +127,7 @@ describe('Table Logic - Sort', () => {
false,
new Contacts('', '', '', '', new Messenger('', 0)),
new Location(new City('', ''), []),
new Business([], [], [], [], [], [], '')
new Business(null, [], [], [], [], [], [], '')
),
]);
});
Expand All @@ -146,7 +146,7 @@ describe('Table Logic - Filter', () => {
false,
new Contacts('', '', '', '', new Messenger('', 0)),
new Location(new City('', ''), []),
new Business([], [], [], [], [], [], '')
new Business(null, [], [], [], [], [], [], '')
),
];
expect(
Expand All @@ -162,7 +162,7 @@ describe('Table Logic - Filter', () => {
false,
new Contacts('', '', '', '', new Messenger('', 0)),
new Location(new City('', ''), []),
new Business([], [], [], [], [], [], '')
new Business(null, [], [], [], [], [], [], '')
),
]);
});
Expand All @@ -179,7 +179,7 @@ describe('Table Logic - Filter', () => {
false,
new Contacts('', '', '', '', new Messenger('', 0)),
new Location(new City('', ''), []),
new Business([], [], [], [], [], [], '')
new Business(null, [], [], [], [], [], [], '')
),
];
expect(
Expand All @@ -199,7 +199,7 @@ describe('Table Logic - Filter', () => {
false,
new Contacts('', '', '', '', new Messenger('', 0)),
new Location(new City('', ''), []),
new Business([], [], [], [], [], [], '')
new Business(null, [], [], [], [], [], [], '')
),
];
expect(
Expand All @@ -219,7 +219,7 @@ describe('Table Logic - Filter', () => {
false,
new Contacts('', '', '', '', new Messenger('', 0)),
new Location(new City('', ''), []),
new Business([], [], [], [], [], [], '')
new Business(null, [], [], [], [], [], [], '')
),
]);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import { inject, TestBed } from '@angular/core/testing';
import { OrganigramService } from './organigram.service';
import { PersonService } from './person.service';
import { HttpClient } from '@angular/common/http';

describe('OrganigramService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [OrganigramService, { provide: PersonService, useValue: null }],
providers: [
OrganigramService,
{ provide: PersonService, useValue: null },
{ provide: HttpClient, useValue: null },
],
});
});

Expand Down
135 changes: 77 additions & 58 deletions Phonebook.Frontend/src/app/services/api/organigram.service.ts
Original file line number Diff line number Diff line change
@@ -1,70 +1,62 @@
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Observable, forkJoin, of } from 'rxjs';
import { map, flatMap, publishReplay, refCount } from 'rxjs/operators';
import { Person } from 'src/app/shared/models';
import { PersonService } from './person.service';
import { HttpClient } from '@angular/common/http';

@Injectable()
export class OrganigramService {
constructor(private personService: PersonService) {}

constructor(private http: HttpClient, private personService: PersonService) {}
public organigram: Observable<UnitTreeNode[]>;
public getOrganigram(): Observable<UnitTreeNode[]> {
return this.personService.getAll().pipe(
map((users) => {
const tree: UnitTreeNode[] = [];
users.forEach((person) => {
if (person.Business.ShortOrgUnit.length === 0) {
return;
}
this.findNodeForPerson(person, tree, 0);
});
return tree;
})
);
}

/**
* Finds the Person's Node in the Hierarchical Structure of Units (generates the Units along its way.)
* @param person The person for whom you like to find the node
* @param nodeChilds The Childs of the node your are currently searching in.
* @param depth The depth of the Tree (to map the Persons Array of Units to the Tree structure)
*/
public findNodeForPerson(person: Person, nodeChilds: UnitTreeNode[], depth: number) {
const firstnode = nodeChilds.find((node) => {
return node.id === person.Business.ShortOrgUnit[depth];
});
if (firstnode === undefined) {
const newNode = new UnitTreeNode(
person.Business.ShortOrgUnit[depth],
person.Business.OrgUnit[depth],
depth
);
if (depth === person.Business.ShortOrgUnit.length - 1) {
this.pushToSpecificGroup(newNode, person);
} else if (person.Business.ShortOrgUnit.length - 1 > depth) {
this.findNodeForPerson(person, newNode.children, depth + 1);
}
nodeChilds.push(newNode);
} else {
if (depth === person.Business.ShortOrgUnit.length - 1) {
this.pushToSpecificGroup(firstnode, person);
return;
} else {
this.findNodeForPerson(person, firstnode.children, depth + 1);
}
if (this.organigram != null) {
return this.organigram;
}
this.organigram = this.http.get<OrgUnit[]>('/api/OrgUnit').pipe(
flatMap((d) => this.ConvertOrgUnitsToUnitTree(d)),
publishReplay(1), // this tells Rx to cache the latest emitted
refCount()
);
return this.organigram;
}

public pushToSpecificGroup(node: UnitTreeNode, person: Person) {
if (person.isLearner()) {
node.learners.push(person);
} else if (person.isSupervisor()) {
node.supervisors.push(person);
} else if (person.isAssistent()) {
node.assistents.push(person);
} else {
node.employees.push(person);
}
private ConvertOrgUnitsToUnitTree(
orgUnits: OrgUnit[],
depth: number = 0
): Observable<UnitTreeNode[]> {
return forkJoin(
orgUnits.map((o) => {
var TaShortNames = o.OrgUnitToFunctions.filter((f) => f.RoleName == 'TA').map(
(t) => t.Person.ShortName
);
return forkJoin(
o.ChildOrgUnits == null || o.ChildOrgUnits.length == 0
? of([])
: this.ConvertOrgUnitsToUnitTree(o.ChildOrgUnits, depth + 1),
o.HeadOfOrgUnit == null
? of(null)
: this.personService.getById(o.HeadOfOrgUnit.ShortName),
TaShortNames.length == 0
? of([])
: forkJoin(TaShortNames.map((shortName) => this.personService.getById(shortName))),
o.ShortName == null ? of([]) : this.personService.getByOrgUnit(o.ShortName)
).pipe(
map(([childs, headofOrgUnit, assistents, members]) => {
var tree = new UnitTreeNode(
o.ShortName == null ? '' : o.ShortName,
o.Name == null ? '' : o.Name,
depth,
o.ChildOrgUnits == null ? [] : childs,
headofOrgUnit == null ? [] : [headofOrgUnit],
assistents.filter((a) => a != null) as Person[],
members.filter((p) => p.isLearner() == false),
members.filter((p) => p.isLearner())
);
return tree;
})
);
})
);
}
}

Expand Down Expand Up @@ -97,3 +89,30 @@ export class UnitTreeNode {
this.learners = learners;
}
}

class OrgUnit {
public Id: number;

public Name?: string;

public ShortName?: string;

public ParentId?: number;
public Parent?: OrgUnit;
public ChildOrgUnits?: OrgUnit[];

public HeadOfOrgUnitId?: number;

public HeadOfOrgUnit?: {
ShortName: string;
};

public CostCenter?: string;
public OrgUnitToFunctions: {
PersonId?: number;
Person: {
ShortName: string;
};
RoleName: string;
}[];
}
Loading