Skip to content

Commit 8b2114e

Browse files
authored
feat(meetings): replace link extraction with attachment api (LFXV2-743) (#154)
* feat(meetings): replace link extraction with attachment API (LFXV2-743) Replace the existing implementation where links are extracted from meeting descriptions with the attachment API that supports link-type attachments. Changes: - Remove extractUrlsWithDomains usage and importantLinks signals from meeting-join and meeting-card components - Update templates to display both file and link attachments uniformly - Add saveLinkAttachments() method to create link attachments from important_links FormArray - Add populateExistingLinks() to load existing links when editing - Add deleteLinkAttachment() handler for tracking link deletions - Update saveLinkAttachments() to only create new links (without uid) - Fix icon alignment with consistent w-8 width for both file and link icons Benefits: - Eliminates duplicate link display from extracted URLs and attachments - Provides consistent CRUD operations for all meeting resources - Links persist as structured data with proper tracking Generated with [Claude Code](https://claude.ai/code) Signed-off-by: Asitha de Silva <[email protected]> * fix(meetings): improve type safety and fix attachment logic - Add ImportantLinkFormValue interface for form-specific link data - Replace any types with proper TypeScript interfaces - Fix pending deletions logic to clear on completion without failures - Fix attachment view/download buttons to check type instead of link field LFXV2-743 Generated with [Claude Code](https://claude.ai/code) Signed-off-by: Asitha de Silva <[email protected]> --------- Signed-off-by: Asitha de Silva <[email protected]>
1 parent 9979d5d commit 8b2114e

File tree

13 files changed

+351
-274
lines changed

13 files changed

+351
-274
lines changed

apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.html

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -237,15 +237,19 @@ <h3 class="text-gray-600 text-sm font-normal">Resources</h3>
237237
<div class="flex flex-col gap-2">
238238
@for (attachment of attachments(); track attachment.uid; let i = $index) {
239239
<a
240-
[href]="'/api/meetings/' + meeting().uid + '/attachments/' + attachment.uid"
240+
[href]="attachment.type === 'link' ? attachment.link : '/api/meetings/' + meeting().uid + '/attachments/' + attachment.uid"
241241
target="_blank"
242242
rel="noopener noreferrer"
243243
class="bg-gray-200 hover:bg-gray-300 rounded px-3 py-2 flex items-center gap-3 min-w-[180px] transition-colors cursor-pointer"
244244
[attr.data-testid]="'meeting-attachment-' + i">
245-
<!-- File Icon -->
246-
<i [class]="(attachment.mime_type || '' | fileTypeIcon) + ' text-3xl text-black'"></i>
247-
248-
<!-- File Name -->
245+
<!-- Icon - File or Link -->
246+
@if (attachment.type === 'link') {
247+
<i class="fa-light fa-arrow-up-right-from-square text-3xl text-black w-8 flex-shrink-0"></i>
248+
} @else {
249+
<i [class]="(attachment.mime_type || '' | fileTypeIcon) + ' text-3xl text-black w-8 flex-shrink-0'"></i>
250+
}
251+
252+
<!-- Attachment Name -->
249253
<span class="text-sm text-neutral-950 overflow-ellipsis overflow-hidden whitespace-nowrap flex-1 font-sans">{{ attachment.name }}</span>
250254
</a>
251255
}

apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,7 @@ import { MeetingRegistrantsComponent } from '@components/meeting-registrants/mee
1818
import { MeetingRsvpDetailsComponent } from '@components/meeting-rsvp-details/meeting-rsvp-details.component';
1919
import { RsvpButtonGroupComponent } from '@components/rsvp-button-group/rsvp-button-group.component';
2020
import { environment } from '@environments/environment';
21-
import {
22-
canJoinMeeting,
23-
extractUrlsWithDomains,
24-
getCurrentOrNextOccurrence,
25-
Meeting,
26-
MeetingAttachment,
27-
MeetingOccurrence,
28-
Project,
29-
User,
30-
} from '@lfx-one/shared';
21+
import { canJoinMeeting, getCurrentOrNextOccurrence, Meeting, MeetingAttachment, MeetingOccurrence, Project, User } from '@lfx-one/shared';
3122
import { FileTypeIconPipe } from '@pipes/file-type-icon.pipe';
3223
import { MeetingTimePipe } from '@pipes/meeting-time.pipe';
3324
import { MeetingService } from '@services/meeting.service';
@@ -78,7 +69,6 @@ export class MeetingJoinComponent {
7869
public meeting: Signal<Meeting & { project: Project }>;
7970
public currentOccurrence: Signal<MeetingOccurrence | null>;
8071
public meetingTypeBadge: Signal<{ badgeClass: string; icon?: string; text: string } | null>;
81-
public importantLinks: Signal<{ url: string; domain: string }[]>;
8272
public returnTo: Signal<string | undefined>;
8373
public password: WritableSignal<string | null> = signal<string | null>(null);
8474
public canJoinMeeting: Signal<boolean>;
@@ -103,7 +93,6 @@ export class MeetingJoinComponent {
10393
this.joinForm = this.initializeJoinForm();
10494
this.formValues = this.initializeFormValues();
10595
this.meetingTypeBadge = this.initializeMeetingTypeBadge();
106-
this.importantLinks = this.initializeImportantLinks();
10796
this.returnTo = this.initializeReturnTo();
10897
this.canJoinMeeting = this.initializeCanJoinMeeting();
10998
this.fetchedJoinUrl = this.initializeFetchedJoinUrl();
@@ -268,20 +257,6 @@ export class MeetingJoinComponent {
268257
});
269258
}
270259

271-
private initializeImportantLinks(): Signal<{ url: string; domain: string }[]> {
272-
return computed(() => {
273-
const meeting = this.meeting();
274-
const currentOccurrence = this.currentOccurrence();
275-
276-
// Use current occurrence description if available, otherwise fallback to meeting description
277-
const description = currentOccurrence?.description || meeting?.description;
278-
if (!description) {
279-
return [];
280-
}
281-
return extractUrlsWithDomains(description);
282-
});
283-
}
284-
285260
private initializeReturnTo(): Signal<string | undefined> {
286261
return computed(() => {
287262
return `${environment.urls.home}/meetings/${this.meeting().uid}?password=${this.password()}`;

apps/lfx-one/src/app/modules/project/committees/components/upcoming-committee-meeting/upcoming-committee-meeting.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<a
88
[routerLink]="['/project', project()?.slug, 'meetings', upcomingMeeting()!.uid]"
99
class="text-sm font-medium text-primary hover:text-primary-600 hover:underline line-clamp-2"
10-
[title]="upcomingMeeting()!.title || 'Meeting'">
10+
[pTooltip]="upcomingMeeting()!.title || 'Meeting'">
1111
{{ upcomingMeeting()!.title || 'Meeting' }}
1212
</a>
1313
</div>

apps/lfx-one/src/app/modules/project/dashboard/project-dashboard/project.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ <h3 class="text-sm font-display text-gray-500">Upcoming Meetings</h3>
183183
<ng-template #body let-row>
184184
<tr>
185185
<td class="w-1/2 max-w-0">
186-
<a class="block truncate text-sm" [title]="row.title" [routerLink]="[row.url]" [relativeTo]="activatedRoute">{{ row.title }}</a>
186+
<a class="block truncate text-sm" [pTooltip]="row.title" [routerLink]="[row.url]" [relativeTo]="activatedRoute">{{ row.title }}</a>
187187
</td>
188188
<td class="w-1/2">
189189
<div class="flex justify-end whitespace-nowrap">
@@ -242,7 +242,7 @@ <h3 class="text-sm font-display text-gray-500">Recently Updated Committees</h3>
242242
<ng-template #body let-row>
243243
<tr>
244244
<td class="w-1/2 max-w-0">
245-
<a class="block truncate text-sm" [title]="row.title" [routerLink]="row.url">{{ row.title }}</a>
245+
<a class="block truncate text-sm" [pTooltip]="row.title" [routerLink]="row.url">{{ row.title }}</a>
246246
</td>
247247
<td class="w-1/2">
248248
<div class="flex justify-end whitespace-nowrap">

apps/lfx-one/src/app/modules/project/meetings/components/meeting-manage/meeting-manage.component.html

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,11 @@ <h1 class="text-xl font-semibold text-slate-900" data-testid="meeting-manage-tit
5555
[existingAttachments]="attachments()"
5656
[isEditMode]="isEditMode()"
5757
[deletingAttachmentId]="deletingAttachmentId()"
58+
[pendingAttachmentDeletions]="pendingAttachmentDeletions()"
5859
(goToStep)="goToStep($event)"
59-
(deleteAttachment)="deleteAttachment($event)">
60+
(deleteAttachment)="deleteAttachment($event)"
61+
(undoDeleteAttachment)="undoDeleteAttachment($event)"
62+
(deleteLinkAttachment)="deleteLinkAttachment($event)">
6063
</lfx-meeting-resources-summary>
6164
</ng-template>
6265
</p-step-panel>
@@ -114,8 +117,10 @@ <h2 class="text-lg font-semibold text-slate-900 mb-4">Resources & Summary</h2>
114117
[existingAttachments]="attachments()"
115118
[isEditMode]="isEditMode()"
116119
[deletingAttachmentId]="deletingAttachmentId()"
120+
[pendingAttachmentDeletions]="pendingAttachmentDeletions()"
117121
(goToStep)="goToStep($event)"
118-
(deleteAttachment)="deleteAttachment($event)">
122+
(deleteAttachment)="deleteAttachment($event)"
123+
(undoDeleteAttachment)="undoDeleteAttachment($event)">
119124
</lfx-meeting-resources-summary>
120125
</div>
121126
</div>

0 commit comments

Comments
 (0)