Skip to content

Commit

Permalink
- Created Walks Import facility for use when a group wishes to switch…
Browse files Browse the repository at this point in the history
… from walks manager population to local

- All walk history is copied from walks manager and attempt is made to match historic walks to existing members in Member Admin
- If no match is found for a detected walk leader, a minimal member record is created and the associated walks are linked to the member
- Changes were made to the Bulk load service to accommodate contact based matching and data population for the above but existing matching logic for monthly data loads remains the same as before
- When walks are imported successfully, a prompt is given the switch walks population to Local.
- If the walks import was not successful, the failing members/walks are highlighted. At this point, it's up to the person running the import to decide whether sufficient historic data is available to continue with the local walks switchover.
- As part of this commit, all references to Assemble names have been removed as Assemble has been decommissioned by Ramblers.
- Due to the creation of the Walks Import, the walks/admin page is now accessible by any member that has Walk Admin privs. Previously this could only be navigated to by a member with Walk Admin privs and the walks population was local.
  • Loading branch information
nbarrett committed Nov 8, 2024
1 parent 58056d3 commit 2f181a8
Show file tree
Hide file tree
Showing 36 changed files with 1,582 additions and 907 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export class DatePickerComponent implements OnInit, OnChanges {

constructor(
private dateUtils: DateUtilsService, loggerFactory: LoggerFactory) {
this.logger = loggerFactory.createLogger("DatePickerComponent", NgxLoggerLevel.OFF);
this.logger = loggerFactory.createLogger("DatePickerComponent", NgxLoggerLevel.ERROR);
}

ngOnChanges(changes: SimpleChanges) {
Expand Down
21 changes: 21 additions & 0 deletions projects/ngx-ramblers/src/app/models/member.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { ApiResponse, Identifiable } from "./api-response.model";
import { MailchimpSubscription } from "./mailchimp.model";
import { MailIdentifiers, MailSubscription } from "./mail.model";
import { sortBy } from "../functions/arrays";
import { Walk } from "./walk.model";
import { Contact } from "./ramblers-walks-manager";

export enum ProfileUpdateType {
LOGIN_DETAILS = "login details",
Expand Down Expand Up @@ -136,9 +138,26 @@ export interface HasEmailFirstAndLastName {
export interface BulkLoadMemberAndMatch {
memberAction: MemberAction;
memberMatchType: string;
contact: Contact;
ramblersMember: RamblersMember;
member: Member;
}

export interface WalksImportPreparation {
bulkLoadMembersAndMatchesToWalks: BulkLoadMemberAndMatchToWalks[];
existingWalksWithinRange: Walk[];
}

export interface BulkLoadMemberAndMatchToWalks {
bulkLoadMemberAndMatch: BulkLoadMemberAndMatch;
walks: Walk[];
}

export interface RamblersMemberAndContact {
contact: Contact;
ramblersMember: RamblersMember;
}

export interface RamblersMember extends HasEmailFirstAndLastName {
groupMember?: boolean;
membershipExpiryDate?: string | number;
Expand Down Expand Up @@ -176,6 +195,8 @@ export interface MemberUpdateAudit extends Auditable {
}

export enum MemberAction {
found = "found",
notFound = "not-found",
created = "created",
complete = "complete",
summary = "summary",
Expand Down
67 changes: 25 additions & 42 deletions projects/ngx-ramblers/src/app/models/ramblers-walks-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,28 @@ export interface MetadataDescription {
export interface Metadata extends MetadataCode, MetadataDescription {
}

export interface WalkLeader {
export interface Contact {
id: string;
name: string;
telephone: string;
has_email: true;
has_email: boolean;
email_form?: string;
is_overridden: false;
is_overridden: boolean;
}

export interface LocationDetails {
latitude: number;
longitude: number;
grid_reference_6: string;
grid_reference_8: string;
postcode: string;
description: string;
w3w: string;
}

export interface Difficulty {
code: string;
description: string;
}

export interface GroupWalk {
Expand All @@ -95,13 +110,7 @@ export interface GroupWalk {
start_date_time: string;
end_date_time: string;
meeting_date_time: string;
event_organiser?: {
name: string;
telephone: string;
has_email: boolean;
is_overridden: boolean;
email_form: string;
},
event_organiser?: Contact,
location?: {
latitude: number;
longitude: number;
Expand All @@ -112,44 +121,17 @@ export interface GroupWalk {
description: string;
w3w: string;
};
start_location: {
latitude: number;
longitude: number;
grid_reference_6: string;
grid_reference_8: string;
postcode: string;
description: string;
w3w: string;
};
meeting_location: {
latitude: number;
longitude: number;
grid_reference_6: string;
grid_reference_8: string;
postcode: string;
description: string;
w3w: string;
};
end_location: {
latitude: number;
longitude: number;
grid_reference_6: string;
grid_reference_8: string;
postcode: string;
description: string;
w3w: string;
};
start_location: LocationDetails;
meeting_location: LocationDetails;
end_location: LocationDetails;
distance_km: number;
distance_miles: number;
ascent_feet: number;
ascent_metres: number;
difficulty: {
code: string;
description: string;
};
difficulty: Difficulty;
shape: string;
duration: number;
walk_leader: WalkLeader;
walk_leader: Contact;
url: string;
external_url: string;
status: WalkStatus;
Expand Down Expand Up @@ -255,3 +237,4 @@ export type WalkUploadRow = {
}

export const ALL_EVENT_TYPES: RamblersEventType[] = [RamblersEventType.GROUP_WALK, RamblersEventType.GROUP_EVENT, RamblersEventType.WELLBEING_WALK];

12 changes: 10 additions & 2 deletions projects/ngx-ramblers/src/app/models/walk.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { WalkAccessMode } from "./walk-edit-mode.model";
import { WalkEventType } from "./walk-event-type.model";
import { WalkEvent } from "./walk-event.model";
import { WalkVenue } from "./walk-venue.model";
import { Metadata, RamblersEventType, WalkLeader } from "./ramblers-walks-manager";
import { Contact, Metadata, RamblersEventType } from "./ramblers-walks-manager";
import { HasMedia } from "./social-events.model";

export interface GoogleMapsConfig {
Expand Down Expand Up @@ -117,7 +117,7 @@ export interface WalkLeaderIdsApiResponse extends ApiResponse {

export interface WalkLeadersApiResponse extends ApiResponse {
request: any;
response?: WalkLeader[];
response?: Contact[];
}

export enum WalkType {
Expand Down Expand Up @@ -192,3 +192,11 @@ export interface FilterParameters extends FilterParametersSearch {
selectType: number;
ascending: boolean;
}

export interface LocalContact {
id?: string;
contactName?: string;
email?: string;
displayName?: string;
telephone?: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { ActionButtonsComponent } from "../common/action-buttons/action-buttons"
import { DynamicContentPageComponent } from "../common/dynamic-content-page/dynamic-content-page";
import { WalksModule } from "./walks.module";
import { WalksPopulationLocalGuard } from "../../guards/walks-population-local-guard";
import { WalkImportComponent } from "../../pages/walks/walk-import/walk-import.component";

@NgModule({
imports: [WalksModule, RouterModule.forChild([
Expand All @@ -29,22 +30,27 @@ import { WalksPopulationLocalGuard } from "../../guards/walks-population-local-g
{
path: "admin",
component: WalkAdminComponent,
canActivate: [WalksAuthGuard, WalksPopulationLocalGuard]
canActivate: [WalksAuthGuard]
},
{
path: "admin/add-walk-slots",
component: WalkAddSlotsComponent,
canActivate: [WalksAuthGuard, WalksPopulationLocalGuard]
canActivate: [WalksAuthGuard]
},
{
path: "admin/export",
component: WalkExportComponent,
canActivate: [WalksAuthGuard, WalksPopulationLocalGuard]
canActivate: [WalksAuthGuard]
},
{
path: "admin/import",
component: WalkImportComponent,
canActivate: [WalksAuthGuard]
},
{
path: "admin/meetup-settings",
component: WalkMeetupSettingsComponent,
canActivate: [WalksAuthGuard, WalksPopulationLocalGuard]
canActivate: [WalksAuthGuard]
},
{
path: "edit/:walk-id",
Expand Down
2 changes: 2 additions & 0 deletions projects/ngx-ramblers/src/app/modules/walks/walks.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ import { SharedModule } from "../../shared-module";
import { WalkFeaturesComponent } from "../../pages/walks/walk-view/walk-features";
import { WalkFeatureComponent } from "../../pages/walks/walk-view/walk-feature";
import { WalkImagesComponent } from "../../pages/walks/walk-view/walk-images";
import { WalkImportComponent } from "../../pages/walks/walk-import/walk-import.component";

@NgModule({
declarations: [
Expand All @@ -92,6 +93,7 @@ import { WalkImagesComponent } from "../../pages/walks/walk-view/walk-images";
WalkEditFullPageComponent,
WalkEventTypePipe,
WalkExportComponent,
WalkImportComponent,
WalkFeatureComponent,
WalkFeaturesComponent,
WalkGroupComponent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ export class DataPopulationService {
name: "mail-settings-process-mappings",
text: "* Listed below are the built-in processes that are utilise email at points in the workflow. \n* This configuration page allows each of the built in processes to be linked to an Email Notification configuration.",
category: "admin"
},
{
name: "ramblers-import-help-page",
text: "This page should be used to prepare your group for when you wish to switch from using Walks Manager as your data source to your local database. There are several reasons why this can be beneficial, including providing better control over the walk leader information published on walks, email-backed workflow such as advertising walk slots and email notifications on change of walk details and the ability to provide more informative fields on the walk that are not supported by Walks Manager. The steps for using this page are to :\n" +
"* Click the **Collect importable walks from Walks Manager** button below to query all walks that are held in Walks manager. This data is then analysed for walk leaders and attempts are made to match them to existing members in your database.\n" +
"* Present statistics on the number of walks and walk leaders with an indication as to whether any missing members should be added.\n" +
"* Click the **Import And Save Walks Locally** button when you are happy with the proposed import information.",
category: "admin"
}
];
const defaultContentTextItems = await Promise.all(defaultContent.map(async (contentText: ContentText) => await this.contentTextService.findOrCreateByNameAndCategory(contentText.name, contentText.category, contentText.text)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,46 +318,18 @@ <h4 class="modal-title">{{editMode}} <em>Member</em> Details</h4>
</div>
<div class="row">
<div class="col col-sm-6">
<label for="ramblers-assemble-name">Ramblers Assemble Name</label>
<label for="ramblers-contact-name">Walks Manager Contact Name</label>
<div class="input-group">
<input autocomplete="new-password" name="contactId" [(ngModel)]="member.contactId" type="text"
class="form-control input-sm" id="ramblers-assemble-name"
placeholder="The first name and last name used in Ramblers Assemble System">
class="form-control input-sm" id="ramblers-contact-name"
placeholder="The first name and last name used in Ramblers contact System">
<div class="input-group-append" tooltip="Set this field to be {{member | fullNameWithAlias}}">
<div class="input-group-text pointer" (click)="defaultAssembleName()">
<div class="input-group-text pointer" (click)="defaultContactName()">
<fa-icon [icon]="faPaste" class="fa-icon"></fa-icon>
</div>
</div>
</div>
</div>
<div class="col col-sm-6">
<form class="form-group">
<label for="assemble-id">Assemble Id</label>
<input autocomplete="new-password" name="assembleId" [(ngModel)]="member.assembleId" type="text"
class="form-control input-sm" id="assemble-id"
placeholder="The Identifier as used in Ramblers Assemble System">
</form>
</div>
<div class="col col-sm-12">
<div class="form-group mb-0">
<label class="title-in-thumbnail">Assemble Links</label>
</div>
<div class="form-group" markdown>
<ul>
<li><a *ngIf="member.assembleId" target="_blank"
[href]="'https://volunteer.ramblers.org.uk/portal/user/'+member.assembleId+'#tab=1'">{{member | fullNameWithAlias}}
's User Details</a>
</li>
<li>
<a target="_blank"
[href]="'https://volunteer.ramblers.org.uk/portal/supervisor/myteam'">View My Team</a>
</li>
<li><a target="_blank"
[href]="'https://volunteer.ramblers.org.uk/portal/supervisor/volunteer/create#type=volunteer&sid'">
Create new Volunteer in Assemble</a></li>
</ul>
</div>
</div>
</div>
</div>
</tab>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ export class MemberAdminModalComponent implements OnInit, OnDestroy {
this.notify.success("Existing Member copied! Make changes here and save to create new member.");
}

defaultAssembleName() {
defaultContactName() {
this.member.contactId = this.fullNameWithAliasPipe.transform(this.member);
}
}
Loading

0 comments on commit 2f181a8

Please sign in to comment.