oip-common 0.11.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -109,7 +109,6 @@ provideOipRoutes({
109
109
  | -------------- | ------------------------------ | -------------------------------------------------- |
110
110
  | `access` | `access` | Redirect target of both guards, keep it registered |
111
111
  | `error` | `error` | |
112
- | `profile` | `profile` | |
113
112
  | `config` | `config` | |
114
113
  | `applications` | `applications` | Administrators only |
115
114
  | `modules` | `modules` | Administrators only |
@@ -1014,7 +1014,9 @@ class BffSecurityService {
1014
1014
  authorize(returnUrl) {
1015
1015
  const normalizedReturnUrl = this.normalizeReturnUrl(returnUrl);
1016
1016
  this.replaceWithUnauthorizedUrl(normalizedReturnUrl);
1017
- const form = this.createPostForm(this.buildUrl('api/security/create-auth-session'));
1017
+ // The return url travels with the request: when a guard rejects the initial navigation, the router
1018
+ // resets the address after this call, so the page address sent as Referer no longer carries it.
1019
+ const form = this.createPostForm(this.buildUrl(`api/security/create-auth-session?returnUrl=${encodeURIComponent(normalizedReturnUrl)}`));
1018
1020
  document.body.appendChild(form);
1019
1021
  form.submit();
1020
1022
  }
@@ -1904,9 +1906,10 @@ class SecurityApi extends HttpClient {
1904
1906
  format: "json",
1905
1907
  ...params,
1906
1908
  });
1907
- this.createAuthSession = (params = {}) => this.request({
1909
+ this.createAuthSession = (query, params = {}) => this.request({
1908
1910
  path: `/api/security/create-auth-session`,
1909
1911
  method: "POST",
1912
+ query: query,
1910
1913
  secure: true,
1911
1914
  ...params,
1912
1915
  });
@@ -2056,14 +2059,14 @@ class SecurityComponent {
2056
2059
  <div class="font-semibold text-xl">
2057
2060
  {{ 'securityComponent.security' | translate }}
2058
2061
  </div>
2059
- @for (item of securityData; track item.name) {
2062
+ @for (item of securityData; track item.code) {
2060
2063
  <div class="flex flex-col gap-2">
2061
- <label htmlFor="oip-security-multiselect-{{ item.name }}">
2064
+ <label htmlFor="oip-security-multiselect-{{ item.code }}">
2062
2065
  {{ item.name }}
2063
2066
  <span class="pi pi-question-circle" pTooltip="{{ item.description }}" tooltipPosition="right"></span>
2064
2067
  </label>
2065
2068
  <p-multiSelect
2066
- id="oip-security-multiselect-{{ item.name }}"
2069
+ id="oip-security-multiselect-{{ item.code }}"
2067
2070
  placeholder="{{ 'securityComponent.selectRoles' | translate }}"
2068
2071
  [maxSelectedLabels]="10"
2069
2072
  [options]="roles"
@@ -2094,14 +2097,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
2094
2097
  <div class="font-semibold text-xl">
2095
2098
  {{ 'securityComponent.security' | translate }}
2096
2099
  </div>
2097
- @for (item of securityData; track item.name) {
2100
+ @for (item of securityData; track item.code) {
2098
2101
  <div class="flex flex-col gap-2">
2099
- <label htmlFor="oip-security-multiselect-{{ item.name }}">
2102
+ <label htmlFor="oip-security-multiselect-{{ item.code }}">
2100
2103
  {{ item.name }}
2101
2104
  <span class="pi pi-question-circle" pTooltip="{{ item.description }}" tooltipPosition="right"></span>
2102
2105
  </label>
2103
2106
  <p-multiSelect
2104
- id="oip-security-multiselect-{{ item.name }}"
2107
+ id="oip-security-multiselect-{{ item.code }}"
2105
2108
  placeholder="{{ 'securityComponent.selectRoles' | translate }}"
2106
2109
  [maxSelectedLabels]="10"
2107
2110
  [options]="roles"
@@ -2918,11 +2921,18 @@ class UserService {
2918
2921
  }
2919
2922
  this.requestedPhotoKey = photoKey;
2920
2923
  this.userProfileApi.getUserPhoto().then((data) => {
2921
- this.createImageFromBlob(data);
2924
+ // 204 No Content comes back as an empty blob: the user hasn't uploaded a photo yet,
2925
+ // so the avatar falls back to initials.
2926
+ const photo = data;
2927
+ if (!photo?.size) {
2928
+ this.photo = null;
2929
+ this.photoLoaded = false;
2930
+ return;
2931
+ }
2932
+ this.createImageFromBlob(photo);
2922
2933
  this.photoLoaded = true;
2923
2934
  }, (error) => {
2924
- // A 404 just means the user hasn't uploaded a photo yet (e.g. on first login) —
2925
- // that's an expected state, not a failure, so fall back to initials silently.
2935
+ // Older backends answer 404 when there is no photo — that's an expected state, not a failure.
2926
2936
  if (error?.status !== 404) {
2927
2937
  this.msgService.errorFromException(error, this.translateService.instant('userService.failedToLoadPhoto'));
2928
2938
  }
@@ -3128,6 +3138,15 @@ class NotificationApi extends HttpClient {
3128
3138
  format: "json",
3129
3139
  ...params,
3130
3140
  });
3141
+ this.createTestNotification = (data, params = {}) => this.request({
3142
+ path: `/api/notification/create-test-notification`,
3143
+ method: "POST",
3144
+ body: data,
3145
+ secure: true,
3146
+ type: ContentType.Json,
3147
+ format: "json",
3148
+ ...params,
3149
+ });
3131
3150
  }
3132
3151
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NotificationApi, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
3133
3152
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NotificationApi }); }
@@ -3338,10 +3357,10 @@ class UserNotificationsComponent {
3338
3357
  } @else {
3339
3358
  <div class="flex flex-col gap-3 max-h-[26rem] overflow-y-auto pr-1">
3340
3359
  @for (notification of notifications; track notification.notificationUserId) {
3341
- <div class="border border-surface-200 dark:border-surface-700 rounded-md p-3">
3360
+ <div class="border border-surface-200 dark:border-surface-700 rounded-md p-3" qa-id="oip-user-notifications-item">
3342
3361
  <div class="flex items-start justify-between gap-3">
3343
3362
  <div class="min-w-0">
3344
- <div class="font-medium leading-snug break-words">
3363
+ <div class="font-medium leading-snug break-words" qa-id="oip-user-notifications-subject">
3345
3364
  {{ notification.subject }}
3346
3365
  </div>
3347
3366
  <div class="text-xs text-surface-500 mt-1">
@@ -3363,6 +3382,7 @@ class UserNotificationsComponent {
3363
3382
  <div class="flex justify-end mt-3">
3364
3383
  <p-button
3365
3384
  icon="pi pi-check"
3385
+ qa-id="oip-user-notifications-mark-as-read"
3366
3386
  size="small"
3367
3387
  [label]="'userNotifications.markAsRead' | translate"
3368
3388
  [loading]="readingNotificationId === notification.notificationUserId"
@@ -3374,6 +3394,7 @@ class UserNotificationsComponent {
3374
3394
 
3375
3395
  <p-paginator
3376
3396
  class="mt-3"
3397
+ qa-id="oip-user-notifications-paginator"
3377
3398
  [first]="skip"
3378
3399
  [rows]="take"
3379
3400
  [rowsPerPageOptions]="[5, 10, 20]"
@@ -3443,10 +3464,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
3443
3464
  } @else {
3444
3465
  <div class="flex flex-col gap-3 max-h-[26rem] overflow-y-auto pr-1">
3445
3466
  @for (notification of notifications; track notification.notificationUserId) {
3446
- <div class="border border-surface-200 dark:border-surface-700 rounded-md p-3">
3467
+ <div class="border border-surface-200 dark:border-surface-700 rounded-md p-3" qa-id="oip-user-notifications-item">
3447
3468
  <div class="flex items-start justify-between gap-3">
3448
3469
  <div class="min-w-0">
3449
- <div class="font-medium leading-snug break-words">
3470
+ <div class="font-medium leading-snug break-words" qa-id="oip-user-notifications-subject">
3450
3471
  {{ notification.subject }}
3451
3472
  </div>
3452
3473
  <div class="text-xs text-surface-500 mt-1">
@@ -3468,6 +3489,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
3468
3489
  <div class="flex justify-end mt-3">
3469
3490
  <p-button
3470
3491
  icon="pi pi-check"
3492
+ qa-id="oip-user-notifications-mark-as-read"
3471
3493
  size="small"
3472
3494
  [label]="'userNotifications.markAsRead' | translate"
3473
3495
  [loading]="readingNotificationId === notification.notificationUserId"
@@ -3479,6 +3501,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
3479
3501
 
3480
3502
  <p-paginator
3481
3503
  class="mt-3"
3504
+ qa-id="oip-user-notifications-paginator"
3482
3505
  [first]="skip"
3483
3506
  [rows]="take"
3484
3507
  [rowsPerPageOptions]="[5, 10, 20]"
@@ -3506,6 +3529,13 @@ class ApplicationsApi extends HttpClient {
3506
3529
  format: "json",
3507
3530
  ...params,
3508
3531
  });
3532
+ this.getAllApplicationRegistryItems = (params = {}) => this.request({
3533
+ path: `/api/applications/get-all-application-registry-items`,
3534
+ method: "GET",
3535
+ secure: true,
3536
+ format: "json",
3537
+ ...params,
3538
+ });
3509
3539
  this.getApplicationRegistryItemByCode = ({ code, ...query }, params = {}) => this.request({
3510
3540
  path: `/api/applications/get-application-registry-item-by-code/${code}`,
3511
3541
  method: "GET",
@@ -6597,11 +6627,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
6597
6627
  }]
6598
6628
  }] });
6599
6629
 
6600
- var userProfile_component = /*#__PURE__*/Object.freeze({
6601
- __proto__: null,
6602
- UserProfileComponent: UserProfileComponent
6603
- });
6604
-
6605
6630
  var config$1 = {
6606
6631
  all: "All",
6607
6632
  applicationManagement: "Application management",
@@ -8477,7 +8502,7 @@ var applications$1 = {
8477
8502
  "delete": "Delete"
8478
8503
  },
8479
8504
  messages: {
8480
- requiredFields: "Fill code, name and Base URL",
8505
+ requiredFields: "Fill code, name, Base URL and Internal Base URL",
8481
8506
  createSuccess: "Application created",
8482
8507
  updateSuccess: "Application updated",
8483
8508
  deleteSuccess: "Application deleted"
@@ -8523,7 +8548,7 @@ var applications = {
8523
8548
  "delete": "Удалить"
8524
8549
  },
8525
8550
  messages: {
8526
- requiredFields: "Заполните код, название и Base URL",
8551
+ requiredFields: "Заполните код, название, Base URL и Internal Base URL",
8527
8552
  createSuccess: "Приложение создано",
8528
8553
  updateSuccess: "Приложение обновлено",
8529
8554
  deleteSuccess: "Приложение удалено"
@@ -8571,7 +8596,7 @@ class ApplicationsComponent {
8571
8596
  this.loading = true;
8572
8597
  this.cancelAllEdits();
8573
8598
  try {
8574
- this.applications = (await this.applicationsApi.getApplicationRegistryItems()).map((application) => ({ ...application }));
8599
+ this.applications = (await this.applicationsApi.getAllApplicationRegistryItems()).map((application) => ({ ...application }));
8575
8600
  this.syncVisibleApplications();
8576
8601
  }
8577
8602
  catch (error) {
@@ -8631,7 +8656,7 @@ class ApplicationsComponent {
8631
8656
  return;
8632
8657
  }
8633
8658
  const request = this.normalizeEditModel(editModel);
8634
- if (!request.code || !request.displayName || !request.baseUrl) {
8659
+ if (!request.code || !request.displayName || !request.baseUrl || !request.internalBaseUrl) {
8635
8660
  this.msgService.error(this.t('applications.messages.requiredFields'));
8636
8661
  return;
8637
8662
  }
@@ -9881,6 +9906,7 @@ class DiscussionComponent {
9881
9906
  <textarea
9882
9907
  class="min-h-28 w-full"
9883
9908
  pTextarea
9909
+ qa-id="oip-discussion-new-comment"
9884
9910
  rows="5"
9885
9911
  [autoResize]="true"
9886
9912
  [placeholder]="'discussionComponent.writeCommentPlaceholder' | translate"
@@ -9904,6 +9930,7 @@ class DiscussionComponent {
9904
9930
  <div class="flex flex-col gap-3">
9905
9931
  @for (candidate of mentionSuggestions; track candidate.userId) {
9906
9932
  <button
9933
+ qa-id="oip-discussion-mention-suggestion"
9907
9934
  class="flex w-full items-center justify-between gap-4 rounded-xl border border-transparent px-3 py-3 text-left transition hover:border-primary-200 hover:bg-primary-50 dark:hover:border-primary-800 dark:hover:bg-primary-950/30"
9908
9935
  type="button"
9909
9936
  (click)="insertMention(candidate)">
@@ -9922,7 +9949,8 @@ class DiscussionComponent {
9922
9949
  <div class="flex flex-col gap-3">
9923
9950
  @for (file of pendingFiles; track file.name + file.size) {
9924
9951
  <div
9925
- class="flex flex-col gap-3 rounded-2xl border border-surface-200 px-4 py-3 sm:flex-row sm:items-center sm:justify-between dark:border-surface-700">
9952
+ class="flex flex-col gap-3 rounded-2xl border border-surface-200 px-4 py-3 sm:flex-row sm:items-center sm:justify-between dark:border-surface-700"
9953
+ qa-id="oip-discussion-pending-file">
9926
9954
  <div class="inline-flex items-center gap-2">
9927
9955
  <i class="pi pi-file"></i>
9928
9956
  <span class="break-all">{{ file.name }}</span>
@@ -9955,10 +9983,11 @@ class DiscussionComponent {
9955
9983
  severity="secondary"
9956
9984
  [label]="'discussionComponent.attachFiles' | translate"
9957
9985
  [text]="true" />
9958
- <input multiple type="file" (change)="onFilesSelected($event)" />
9986
+ <input multiple qa-id="oip-discussion-attach-input" type="file" (change)="onFilesSelected($event)" />
9959
9987
  </label>
9960
9988
  <p-button
9961
9989
  icon="pi pi-send"
9990
+ qa-id="oip-discussion-send"
9962
9991
  [disabled]="submitting || !newComment.trim()"
9963
9992
  [label]="'discussionComponent.send' | translate"
9964
9993
  [loading]="submitting"
@@ -9982,7 +10011,7 @@ class DiscussionComponent {
9982
10011
  } @else {
9983
10012
  <div class="flex flex-col gap-4">
9984
10013
  @for (comment of comments; track comment.commentId) {
9985
- <p-card class="block">
10014
+ <p-card class="block" qa-id="oip-discussion-comment">
9986
10015
  <ng-template pTemplate="content">
9987
10016
  <div class="grid gap-4 md:grid-cols-[3.2rem_minmax(0,1fr)]">
9988
10017
  <div>
@@ -10003,6 +10032,7 @@ class DiscussionComponent {
10003
10032
  @if (comment.isEdited) {
10004
10033
  <p-tag
10005
10034
  icon="pi pi-pencil"
10035
+ qa-id="oip-discussion-comment-edited"
10006
10036
  severity="warn"
10007
10037
  [value]="'discussionComponent.edited' | translate" />
10008
10038
  }
@@ -10010,6 +10040,7 @@ class DiscussionComponent {
10010
10040
  @if (comment.canEdit) {
10011
10041
  <p-button
10012
10042
  icon="pi pi-pencil"
10043
+ qa-id="oip-discussion-comment-edit"
10013
10044
  severity="secondary"
10014
10045
  [rounded]="true"
10015
10046
  [text]="true"
@@ -10018,6 +10049,7 @@ class DiscussionComponent {
10018
10049
  @if (comment.historyCount > 0) {
10019
10050
  <p-button
10020
10051
  icon="pi pi-history"
10052
+ qa-id="oip-discussion-comment-history"
10021
10053
  severity="secondary"
10022
10054
  [rounded]="true"
10023
10055
  [text]="true"
@@ -10026,6 +10058,7 @@ class DiscussionComponent {
10026
10058
  @if (comment.canDelete) {
10027
10059
  <p-button
10028
10060
  icon="pi pi-trash"
10061
+ qa-id="oip-discussion-comment-delete"
10029
10062
  severity="danger"
10030
10063
  [rounded]="true"
10031
10064
  [text]="true"
@@ -10038,6 +10071,7 @@ class DiscussionComponent {
10038
10071
  <textarea
10039
10072
  class="min-h-24 w-full"
10040
10073
  pTextarea
10074
+ qa-id="oip-discussion-edit-content"
10041
10075
  rows="4"
10042
10076
  [autoResize]="true"
10043
10077
  [placeholder]="'discussionComponent.editCommentPlaceholder' | translate"
@@ -10056,6 +10090,7 @@ class DiscussionComponent {
10056
10090
 
10057
10091
  <p-button
10058
10092
  icon="pi pi-check"
10093
+ qa-id="oip-discussion-edit-save"
10059
10094
  [disabled]="!editContent.trim()"
10060
10095
  [label]="'discussionComponent.save' | translate"
10061
10096
  (onClick)="saveEdit(comment)" />
@@ -10068,17 +10103,23 @@ class DiscussionComponent {
10068
10103
  </div>
10069
10104
  </div>
10070
10105
  } @else {
10071
- <div class="markdown-preview" [innerHTML]="renderMarkdown(comment.content)"></div>
10106
+ <div
10107
+ class="markdown-preview"
10108
+ qa-id="oip-discussion-comment-content"
10109
+ [innerHTML]="renderMarkdown(comment.content)"></div>
10072
10110
  }
10073
10111
 
10074
10112
  @if (comment.attachments.length > 0) {
10075
10113
  <div class="flex flex-col gap-3">
10076
10114
  <div class="flex flex-col gap-3">
10077
10115
  @for (attachment of comment.attachments; track attachment.attachmentId) {
10078
- <div class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-end">
10116
+ <div
10117
+ class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-end"
10118
+ qa-id="oip-discussion-attachment">
10079
10119
  <div class="inline-flex items-center gap-2">
10080
10120
  <i class="pi pi-file"></i>
10081
10121
  <button
10122
+ qa-id="oip-discussion-attachment-name"
10082
10123
  class="break-all bg-transparent p-0 text-left font-semibold text-primary-600 transition hover:text-primary-500"
10083
10124
  type="button"
10084
10125
  (click)="downloadAttachment(attachment)">
@@ -10090,6 +10131,7 @@ class DiscussionComponent {
10090
10131
  @if (comment.canEdit) {
10091
10132
  <p-button
10092
10133
  icon="pi pi-times"
10134
+ qa-id="oip-discussion-attachment-delete"
10093
10135
  severity="danger"
10094
10136
  [rounded]="true"
10095
10137
  [text]="true"
@@ -10104,6 +10146,7 @@ class DiscussionComponent {
10104
10146
  <div class="flex flex-wrap items-center gap-2">
10105
10147
  @for (reaction of getReactions(comment); track reaction.emojiCode) {
10106
10148
  <p-button
10149
+ qa-id="oip-discussion-reaction"
10107
10150
  severity="secondary"
10108
10151
  [label]="reaction.emojiCode + ' ' + reaction.count"
10109
10152
  [outlined]="false"
@@ -10113,6 +10156,7 @@ class DiscussionComponent {
10113
10156
  @if (!hasUserReaction(comment)) {
10114
10157
  <p-button
10115
10158
  icon="pi pi-face-smile"
10159
+ qa-id="oip-discussion-add-reaction"
10116
10160
  severity="secondary"
10117
10161
  [rounded]="true"
10118
10162
  [text]="true"
@@ -10122,6 +10166,7 @@ class DiscussionComponent {
10122
10166
  @for (emoji of emojiPalette; track emoji) {
10123
10167
  <button
10124
10168
  class="emoji-option"
10169
+ qa-id="oip-discussion-emoji"
10125
10170
  type="button"
10126
10171
  (click)="reactWithEmoji(comment, emoji, reactionPopover)">
10127
10172
  {{ emoji }}
@@ -10152,7 +10197,9 @@ class DiscussionComponent {
10152
10197
  item of historyByComment[comment.commentId]?.items ?? [];
10153
10198
  track item.commentEditHistoryId
10154
10199
  ) {
10155
- <div class="rounded-2xl border border-surface-200 px-4 py-4 dark:border-surface-700">
10200
+ <div
10201
+ class="rounded-2xl border border-surface-200 px-4 py-4 dark:border-surface-700"
10202
+ qa-id="oip-discussion-history-item">
10156
10203
  <div class="mb-3 inline-flex items-center gap-2 text-sm font-semibold">
10157
10204
  <i class="pi pi-clock"></i>
10158
10205
  <span>{{ item.editedByDisplayName }} · {{ item.editedAt | date: 'short' }}</span>
@@ -10162,12 +10209,14 @@ class DiscussionComponent {
10162
10209
  <p-tag severity="secondary" [value]="'discussionComponent.before' | translate" />
10163
10210
  <div
10164
10211
  class="history-markdown rounded-2xl bg-surface-50 px-4 py-3 leading-7 dark:bg-surface-900/40"
10212
+ qa-id="oip-discussion-history-old"
10165
10213
  [innerHTML]="renderMarkdown(item.oldContent)"></div>
10166
10214
  </div>
10167
10215
  <div class="flex flex-col gap-2">
10168
10216
  <p-tag severity="success" [value]="'discussionComponent.after' | translate" />
10169
10217
  <div
10170
10218
  class="history-markdown rounded-2xl bg-surface-50 px-4 py-3 leading-7 dark:bg-surface-900/40"
10219
+ qa-id="oip-discussion-history-new"
10171
10220
  [innerHTML]="renderMarkdown(item.newContent)"></div>
10172
10221
  </div>
10173
10222
  </div>
@@ -10214,6 +10263,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
10214
10263
  <textarea
10215
10264
  class="min-h-28 w-full"
10216
10265
  pTextarea
10266
+ qa-id="oip-discussion-new-comment"
10217
10267
  rows="5"
10218
10268
  [autoResize]="true"
10219
10269
  [placeholder]="'discussionComponent.writeCommentPlaceholder' | translate"
@@ -10237,6 +10287,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
10237
10287
  <div class="flex flex-col gap-3">
10238
10288
  @for (candidate of mentionSuggestions; track candidate.userId) {
10239
10289
  <button
10290
+ qa-id="oip-discussion-mention-suggestion"
10240
10291
  class="flex w-full items-center justify-between gap-4 rounded-xl border border-transparent px-3 py-3 text-left transition hover:border-primary-200 hover:bg-primary-50 dark:hover:border-primary-800 dark:hover:bg-primary-950/30"
10241
10292
  type="button"
10242
10293
  (click)="insertMention(candidate)">
@@ -10255,7 +10306,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
10255
10306
  <div class="flex flex-col gap-3">
10256
10307
  @for (file of pendingFiles; track file.name + file.size) {
10257
10308
  <div
10258
- class="flex flex-col gap-3 rounded-2xl border border-surface-200 px-4 py-3 sm:flex-row sm:items-center sm:justify-between dark:border-surface-700">
10309
+ class="flex flex-col gap-3 rounded-2xl border border-surface-200 px-4 py-3 sm:flex-row sm:items-center sm:justify-between dark:border-surface-700"
10310
+ qa-id="oip-discussion-pending-file">
10259
10311
  <div class="inline-flex items-center gap-2">
10260
10312
  <i class="pi pi-file"></i>
10261
10313
  <span class="break-all">{{ file.name }}</span>
@@ -10288,10 +10340,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
10288
10340
  severity="secondary"
10289
10341
  [label]="'discussionComponent.attachFiles' | translate"
10290
10342
  [text]="true" />
10291
- <input multiple type="file" (change)="onFilesSelected($event)" />
10343
+ <input multiple qa-id="oip-discussion-attach-input" type="file" (change)="onFilesSelected($event)" />
10292
10344
  </label>
10293
10345
  <p-button
10294
10346
  icon="pi pi-send"
10347
+ qa-id="oip-discussion-send"
10295
10348
  [disabled]="submitting || !newComment.trim()"
10296
10349
  [label]="'discussionComponent.send' | translate"
10297
10350
  [loading]="submitting"
@@ -10315,7 +10368,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
10315
10368
  } @else {
10316
10369
  <div class="flex flex-col gap-4">
10317
10370
  @for (comment of comments; track comment.commentId) {
10318
- <p-card class="block">
10371
+ <p-card class="block" qa-id="oip-discussion-comment">
10319
10372
  <ng-template pTemplate="content">
10320
10373
  <div class="grid gap-4 md:grid-cols-[3.2rem_minmax(0,1fr)]">
10321
10374
  <div>
@@ -10336,6 +10389,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
10336
10389
  @if (comment.isEdited) {
10337
10390
  <p-tag
10338
10391
  icon="pi pi-pencil"
10392
+ qa-id="oip-discussion-comment-edited"
10339
10393
  severity="warn"
10340
10394
  [value]="'discussionComponent.edited' | translate" />
10341
10395
  }
@@ -10343,6 +10397,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
10343
10397
  @if (comment.canEdit) {
10344
10398
  <p-button
10345
10399
  icon="pi pi-pencil"
10400
+ qa-id="oip-discussion-comment-edit"
10346
10401
  severity="secondary"
10347
10402
  [rounded]="true"
10348
10403
  [text]="true"
@@ -10351,6 +10406,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
10351
10406
  @if (comment.historyCount > 0) {
10352
10407
  <p-button
10353
10408
  icon="pi pi-history"
10409
+ qa-id="oip-discussion-comment-history"
10354
10410
  severity="secondary"
10355
10411
  [rounded]="true"
10356
10412
  [text]="true"
@@ -10359,6 +10415,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
10359
10415
  @if (comment.canDelete) {
10360
10416
  <p-button
10361
10417
  icon="pi pi-trash"
10418
+ qa-id="oip-discussion-comment-delete"
10362
10419
  severity="danger"
10363
10420
  [rounded]="true"
10364
10421
  [text]="true"
@@ -10371,6 +10428,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
10371
10428
  <textarea
10372
10429
  class="min-h-24 w-full"
10373
10430
  pTextarea
10431
+ qa-id="oip-discussion-edit-content"
10374
10432
  rows="4"
10375
10433
  [autoResize]="true"
10376
10434
  [placeholder]="'discussionComponent.editCommentPlaceholder' | translate"
@@ -10389,6 +10447,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
10389
10447
 
10390
10448
  <p-button
10391
10449
  icon="pi pi-check"
10450
+ qa-id="oip-discussion-edit-save"
10392
10451
  [disabled]="!editContent.trim()"
10393
10452
  [label]="'discussionComponent.save' | translate"
10394
10453
  (onClick)="saveEdit(comment)" />
@@ -10401,17 +10460,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
10401
10460
  </div>
10402
10461
  </div>
10403
10462
  } @else {
10404
- <div class="markdown-preview" [innerHTML]="renderMarkdown(comment.content)"></div>
10463
+ <div
10464
+ class="markdown-preview"
10465
+ qa-id="oip-discussion-comment-content"
10466
+ [innerHTML]="renderMarkdown(comment.content)"></div>
10405
10467
  }
10406
10468
 
10407
10469
  @if (comment.attachments.length > 0) {
10408
10470
  <div class="flex flex-col gap-3">
10409
10471
  <div class="flex flex-col gap-3">
10410
10472
  @for (attachment of comment.attachments; track attachment.attachmentId) {
10411
- <div class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-end">
10473
+ <div
10474
+ class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-end"
10475
+ qa-id="oip-discussion-attachment">
10412
10476
  <div class="inline-flex items-center gap-2">
10413
10477
  <i class="pi pi-file"></i>
10414
10478
  <button
10479
+ qa-id="oip-discussion-attachment-name"
10415
10480
  class="break-all bg-transparent p-0 text-left font-semibold text-primary-600 transition hover:text-primary-500"
10416
10481
  type="button"
10417
10482
  (click)="downloadAttachment(attachment)">
@@ -10423,6 +10488,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
10423
10488
  @if (comment.canEdit) {
10424
10489
  <p-button
10425
10490
  icon="pi pi-times"
10491
+ qa-id="oip-discussion-attachment-delete"
10426
10492
  severity="danger"
10427
10493
  [rounded]="true"
10428
10494
  [text]="true"
@@ -10437,6 +10503,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
10437
10503
  <div class="flex flex-wrap items-center gap-2">
10438
10504
  @for (reaction of getReactions(comment); track reaction.emojiCode) {
10439
10505
  <p-button
10506
+ qa-id="oip-discussion-reaction"
10440
10507
  severity="secondary"
10441
10508
  [label]="reaction.emojiCode + ' ' + reaction.count"
10442
10509
  [outlined]="false"
@@ -10446,6 +10513,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
10446
10513
  @if (!hasUserReaction(comment)) {
10447
10514
  <p-button
10448
10515
  icon="pi pi-face-smile"
10516
+ qa-id="oip-discussion-add-reaction"
10449
10517
  severity="secondary"
10450
10518
  [rounded]="true"
10451
10519
  [text]="true"
@@ -10455,6 +10523,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
10455
10523
  @for (emoji of emojiPalette; track emoji) {
10456
10524
  <button
10457
10525
  class="emoji-option"
10526
+ qa-id="oip-discussion-emoji"
10458
10527
  type="button"
10459
10528
  (click)="reactWithEmoji(comment, emoji, reactionPopover)">
10460
10529
  {{ emoji }}
@@ -10485,7 +10554,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
10485
10554
  item of historyByComment[comment.commentId]?.items ?? [];
10486
10555
  track item.commentEditHistoryId
10487
10556
  ) {
10488
- <div class="rounded-2xl border border-surface-200 px-4 py-4 dark:border-surface-700">
10557
+ <div
10558
+ class="rounded-2xl border border-surface-200 px-4 py-4 dark:border-surface-700"
10559
+ qa-id="oip-discussion-history-item">
10489
10560
  <div class="mb-3 inline-flex items-center gap-2 text-sm font-semibold">
10490
10561
  <i class="pi pi-clock"></i>
10491
10562
  <span>{{ item.editedByDisplayName }} · {{ item.editedAt | date: 'short' }}</span>
@@ -10495,12 +10566,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
10495
10566
  <p-tag severity="secondary" [value]="'discussionComponent.before' | translate" />
10496
10567
  <div
10497
10568
  class="history-markdown rounded-2xl bg-surface-50 px-4 py-3 leading-7 dark:bg-surface-900/40"
10569
+ qa-id="oip-discussion-history-old"
10498
10570
  [innerHTML]="renderMarkdown(item.oldContent)"></div>
10499
10571
  </div>
10500
10572
  <div class="flex flex-col gap-2">
10501
10573
  <p-tag severity="success" [value]="'discussionComponent.after' | translate" />
10502
10574
  <div
10503
10575
  class="history-markdown rounded-2xl bg-surface-50 px-4 py-3 leading-7 dark:bg-surface-900/40"
10576
+ qa-id="oip-discussion-history-new"
10504
10577
  [innerHTML]="renderMarkdown(item.newContent)"></div>
10505
10578
  </div>
10506
10579
  </div>
@@ -11738,14 +11811,6 @@ function oipErrorRoute(path = 'error') {
11738
11811
  loadComponent: () => Promise.resolve().then(function () { return error_component; }).then((m) => m.ErrorComponent)
11739
11812
  };
11740
11813
  }
11741
- /** Current user profile. */
11742
- function oipProfileRoute(path = 'profile') {
11743
- return {
11744
- path,
11745
- loadComponent: () => Promise.resolve().then(function () { return userProfile_component; }).then((m) => m.UserProfileComponent),
11746
- canActivate: [oipAuthGuard]
11747
- };
11748
- }
11749
11814
  /** Application configuration. */
11750
11815
  function oipConfigRoute(path = 'config') {
11751
11816
  return {
@@ -11844,7 +11909,6 @@ function provideOipRoutes(options = {}) {
11844
11909
  const children = [...(options.children ?? [])];
11845
11910
  builtInRoute(features.access, oipAccessRoute, children);
11846
11911
  builtInRoute(features.error, oipErrorRoute, children);
11847
- builtInRoute(features.profile, oipProfileRoute, children);
11848
11912
  builtInRoute(features.config, oipConfigRoute, children);
11849
11913
  builtInRoute(features.applications, oipApplicationsRoute, children);
11850
11914
  builtInRoute(features.modules, oipModulesRoute, children);
@@ -11888,5 +11952,5 @@ function provideOipRoutes(options = {}) {
11888
11952
  * Generated bundle index. Do not edit.
11889
11953
  */
11890
11954
 
11891
- export { APP_INFO_TOKEN, APP_THEME_PRESETS, APP_THEME_PRESETS_MERGE_MODE, AccessComponent, AppConfiguratorComponent, AppFloatingConfiguratorComponent, AppInfoService, AppLayoutComponent, AppModulesComponent, AppTopbar, AppTopbarApplicationSwitcherComponent, ApplicationRegistryService, ApplicationsApi, ApplicationsComponent, AuthGuardService, AuthSessionsApi, AuthSessionsComponent, BaseModuleComponent, BffSecurityService, BlockLoaderComponent, ConfigComponent, ContentType, CustomElementExtensionModuleHostComponent, DbMigrationComponent, DefaultSecretsBannerComponent, DiscussionComponent, ErrorComponent, ExtensionLoaderService, ExtensionModuleHostComponent, FolderModuleApi, FooterComponent, HttpClient, IframeModuleApi, IframeModuleComponent, L10nService, LOGO_COMPONENT_TOKEN, LayoutService, LogoComponent, LogoService, MenuComponent, MenuService, ModuleInstanceRightsService, ModuleLoadingService, MsgService, NoModulesComponent, NotfoundComponent, NotificationApi, NotificationService, OIP_EXTENSION_EVENTS, SecurityApi, SecurityComponent, SecurityService, SidebarComponent, StartPageService, TableFilterService, TopBarService, UnauthorizedComponent, UserNotificationsComponent, UserProfileApi, UserProfileComponent, UserService, convertToPrimeNgDateFormat, defaultTheme, emitOipContextChange, emitOipError, emitOipNavigate, emitOipNotify, emitOipSettingsChange, emitOipTitleChange, langIntercept, mergeWithDefaults, moduleAccessGuard, oipAccessRoute, oipApplicationsRoute, oipAuthGuard, oipConfigRoute, oipDbMigrationRoute, oipDiscussionRoute, oipErrorRoute, oipExtensionsRoute, oipIframeModuleRoute, oipModulesRoute, oipNoModulesRoute, oipProfileRoute, oipSessionsRoute, oipStartRedirectGuard, oipStartRoute, provideAppInfo, provideAppThemes, provideLogoComponent, provideOip, provideOipRoutes, provideTranslations, replaceDefaults };
11955
+ export { APP_INFO_TOKEN, APP_THEME_PRESETS, APP_THEME_PRESETS_MERGE_MODE, AccessComponent, AppConfiguratorComponent, AppFloatingConfiguratorComponent, AppInfoService, AppLayoutComponent, AppModulesComponent, AppTopbar, AppTopbarApplicationSwitcherComponent, ApplicationRegistryService, ApplicationsApi, ApplicationsComponent, AuthGuardService, AuthSessionsApi, AuthSessionsComponent, BaseModuleComponent, BffSecurityService, BlockLoaderComponent, ConfigComponent, ContentType, CustomElementExtensionModuleHostComponent, DbMigrationComponent, DefaultSecretsBannerComponent, DiscussionComponent, ErrorComponent, ExtensionLoaderService, ExtensionModuleHostComponent, FolderModuleApi, FooterComponent, HttpClient, IframeModuleApi, IframeModuleComponent, L10nService, LOGO_COMPONENT_TOKEN, LayoutService, LogoComponent, LogoService, MenuComponent, MenuService, ModuleInstanceRightsService, ModuleLoadingService, MsgService, NoModulesComponent, NotfoundComponent, NotificationApi, NotificationService, OIP_EXTENSION_EVENTS, SecurityApi, SecurityComponent, SecurityService, SidebarComponent, StartPageService, TableFilterService, TopBarService, UnauthorizedComponent, UserNotificationsComponent, UserProfileApi, UserProfileComponent, UserService, convertToPrimeNgDateFormat, defaultTheme, emitOipContextChange, emitOipError, emitOipNavigate, emitOipNotify, emitOipSettingsChange, emitOipTitleChange, langIntercept, mergeWithDefaults, moduleAccessGuard, oipAccessRoute, oipApplicationsRoute, oipAuthGuard, oipConfigRoute, oipDbMigrationRoute, oipDiscussionRoute, oipErrorRoute, oipExtensionsRoute, oipIframeModuleRoute, oipModulesRoute, oipNoModulesRoute, oipSessionsRoute, oipStartRedirectGuard, oipStartRoute, provideAppInfo, provideAppThemes, provideLogoComponent, provideOip, provideOipRoutes, provideTranslations, replaceDefaults };
11892
11956
  //# sourceMappingURL=oip-common.mjs.map