• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

geonetwork / geonetwork-ui / 14644359047

24 Apr 2025 02:35PM UTC coverage: 82.21% (+0.03%) from 82.183%
14644359047

Pull #1203

github

web-flow
Merge 39ad44a96 into 26001d617
Pull Request #1203: New truncate text component

1952 of 2729 branches covered (71.53%)

Branch coverage included in aggregate %.

21 of 22 new or added lines in 2 files covered. (95.45%)

15 existing lines in 2 files now uncovered.

6417 of 7451 relevant lines covered (86.12%)

10.93 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.3
/apps/metadata-editor/src/app/edit/edit-page.component.ts
1
import { CommonModule } from '@angular/common'
3✔
2
import {
3✔
3
  Component,
4
  ElementRef,
5
  OnDestroy,
6
  OnInit,
7
  ViewChild,
8
} from '@angular/core'
9
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'
3✔
10
import { ActivatedRoute, Router } from '@angular/router'
3✔
11
import { marker } from '@biesbjerg/ngx-translate-extract-marker'
3✔
12
import { PublicationVersionError } from '@geonetwork-ui/common/domain/model/error'
3✔
13
import {
3✔
14
  EditorFacade,
15
  MultilingualPanelComponent,
16
  RecordFormComponent,
17
} from '@geonetwork-ui/feature/editor'
18
import {
3✔
19
  NotificationsContainerComponent,
20
  NotificationsService,
21
} from '@geonetwork-ui/feature/notifications'
22
import { ButtonComponent, CheckToggleComponent } from '@geonetwork-ui/ui/inputs'
3✔
23
import { TranslateModule, TranslateService } from '@ngx-translate/core'
3✔
24
import { combineLatest, filter, firstValueFrom, Subscription, take } from 'rxjs'
3✔
25
import { map, skip } from 'rxjs/operators'
3✔
26
import { SidebarComponent } from '../dashboard/sidebar/sidebar.component'
3✔
27
import { PageSelectorComponent } from './components/page-selector/page-selector.component'
3✔
28
import { TopToolbarComponent } from './components/top-toolbar/top-toolbar.component'
3✔
29
import { SpinningLoaderComponent } from '@geonetwork-ui/ui/widgets'
3✔
30
import { SearchHeaderComponent } from '../dashboard/search-header/search-header.component'
3✔
31
import { PageErrorComponent } from './components/page-error/page-error.component'
3✔
32
import { DateService } from '@geonetwork-ui/util/shared'
3✔
33

34
marker('editor.record.form.bottomButtons.comeBackLater')
3✔
35
marker('editor.record.form.bottomButtons.previous')
3✔
36
marker('editor.record.form.bottomButtons.next')
3✔
37

38
@Component({
39
  selector: 'md-editor-edit',
40
  templateUrl: './edit-page.component.html',
41
  styleUrls: ['./edit-page.component.css'],
42
  standalone: true,
43
  imports: [
44
    RecordFormComponent,
45
    CommonModule,
46
    ButtonComponent,
47
    MatProgressSpinnerModule,
48
    TopToolbarComponent,
49
    NotificationsContainerComponent,
50
    PageSelectorComponent,
51
    TranslateModule,
52
    SidebarComponent,
53
    SpinningLoaderComponent,
54
    SearchHeaderComponent,
55
    PageErrorComponent,
56
    MultilingualPanelComponent,
57
  ],
58
})
59
export class EditPageComponent implements OnInit, OnDestroy {
3✔
60
  subscription = new Subscription()
12✔
61

62
  currentPage$ = this.facade.currentPage$
12✔
63
  pagesLength$ = this.facade.editorConfig$.pipe(
12✔
64
    map((config) => config.pages.length)
2✔
65
  )
66
  isLastPage$ = combineLatest([this.currentPage$, this.pagesLength$]).pipe(
12✔
67
    map(([currentPage, pagesCount]) => currentPage >= pagesCount - 1)
2✔
68
  )
69
  hasRecordChanged$ = this.facade.hasRecordChanged$.pipe(skip(1))
12✔
70

71
  newRecord = false
12✔
72
  isLoading = true
12✔
73
  translatePanelOpen = false
12✔
74

75
  @ViewChild('scrollContainer') scrollContainer: ElementRef<HTMLElement>
76

77
  constructor(
78
    private route: ActivatedRoute,
12!
79
    protected facade: EditorFacade,
12!
80
    private notificationsService: NotificationsService,
12!
81
    private translateService: TranslateService,
12!
82
    private router: Router,
12!
83
    private dateService: DateService
12✔
84
  ) {}
85

86
  ngOnInit(): void {
87
    const [currentRecord, currentRecordSource] =
88
      this.route.snapshot.data['record']
10✔
89

90
    this.facade.openRecord(currentRecord, currentRecordSource)
10✔
91

92
    this.subscription.add(
10✔
93
      this.facade.record$.pipe(take(1)).subscribe((record) => {
94
        if (!record.uniqueIdentifier) {
10✔
95
          this.newRecord = true
1✔
96
          this.facade.saveRecord()
1✔
97
        } else {
98
          this.isLoading = false
9✔
99
        }
100
      })
101
    )
102

103
    this.subscription.add(
10✔
104
      this.facade.saveError$.subscribe((error) => {
105
        if (error instanceof PublicationVersionError) {
2✔
106
          this.notificationsService.showNotification(
1✔
107
            {
108
              type: 'error',
109
              title: this.translateService.instant(
110
                'editor.record.publishVersionError.title'
111
              ),
112
              text: this.translateService.instant(
113
                'editor.record.publishVersionError.body',
114
                { currentVersion: error.detectedApiVersion }
115
              ),
116
              closeMessage: this.translateService.instant(
117
                'editor.record.publishVersionError.closeMessage'
118
              ),
119
            },
120
            undefined,
121
            error
122
          )
123
        } else {
124
          this.notificationsService.showNotification(
1✔
125
            {
126
              type: 'error',
127
              title: this.translateService.instant(
128
                'editor.record.publishError.title'
129
              ),
130
              text: `${this.translateService.instant(
131
                'editor.record.publishError.body'
132
              )} ${error.message}`,
133
              closeMessage: this.translateService.instant(
134
                'editor.record.publishError.closeMessage'
135
              ),
136
            },
137
            undefined,
138
            error
139
          )
140
        }
141
      })
142
    )
143

144
    this.subscription.add(
10✔
145
      this.facade.saveSuccess$.subscribe(() => {
146
        if (!this.newRecord) {
1✔
147
          this.notificationsService.showNotification(
1✔
148
            {
149
              type: 'success',
150
              title: this.translateService.instant(
151
                'editor.record.publishSuccess.title'
152
              ),
153
              text: `${this.translateService.instant(
154
                'editor.record.publishSuccess.body'
155
              )}`,
156
            },
157
            2500
158
          )
159
        }
160
      })
161
    )
162

163
    this.subscription.add(
10✔
164
      this.facade.record$.subscribe((record) => {
165
        this.facade.checkHasRecordChanged(record)
11✔
166
      })
167
    )
168

169
    // if we're on the /duplicate route, go to /edit/{uuid} to update the uuid
170
    if (this.route.snapshot.routeConfig?.path.includes('duplicate')) {
10!
UNCOV
171
      this.router.navigate(['edit', currentRecord.uniqueIdentifier], {
×
172
        replaceUrl: true,
173
      })
174
    }
175

176
    // if the record unique identifier changes, navigate to /edit/newUuid
177
    this.subscription.add(
10✔
178
      this.facade.record$
179
        .pipe(
180
          filter(
181
            (record) =>
182
              record?.uniqueIdentifier !== currentRecord.uniqueIdentifier
10✔
183
          ),
184
          take(1)
185
        )
186
        .subscribe((savedRecord) => {
187
          this.router.navigate(['edit', savedRecord.uniqueIdentifier], {
2✔
188
            replaceUrl: true,
189
          })
190
        })
191
    )
192
  }
193

194
  ngOnDestroy() {
195
    this.subscription.unsubscribe()
13✔
196
  }
197

198
  async previousPageButtonHandler() {
UNCOV
199
    const currentPage = await firstValueFrom(this.currentPage$)
×
200
    if (currentPage === 0) {
×
201
      this.router.navigate(['catalog', 'search'])
×
202
    } else {
UNCOV
203
      this.facade.setCurrentPage(currentPage - 1)
×
UNCOV
204
      this.scrollToTop()
×
205
    }
206
  }
207

208
  async nextPageButtonHandler() {
209
    const currentPage = await firstValueFrom(this.currentPage$)
×
210
    const pagesCount = await firstValueFrom(this.pagesLength$)
×
UNCOV
211
    if (currentPage < pagesCount - 1) {
×
UNCOV
212
      this.facade.setCurrentPage(currentPage + 1)
×
UNCOV
213
      this.scrollToTop()
×
214
    }
215
  }
216

217
  private scrollToTop() {
UNCOV
218
    this.scrollContainer.nativeElement.scroll({
×
219
      behavior: 'instant',
220
      top: 0,
221
    })
222
  }
223

224
  formatDate(date: Date): string {
UNCOV
225
    return this.dateService.formatDate(date, {
×
226
      year: 'numeric',
227
      month: 'long',
228
      day: 'numeric',
229
      hour: 'numeric',
230
      minute: 'numeric',
231
    })
232
  }
233
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc