diff --git a/src/app/shared/components/wiki/compare-section/compare-section.component.html b/src/app/shared/components/wiki/compare-section/compare-section.component.html index 9969a838e..80e0b801c 100644 --- a/src/app/shared/components/wiki/compare-section/compare-section.component.html +++ b/src/app/shared/components/wiki/compare-section/compare-section.component.html @@ -8,17 +8,20 @@

{{ 'project.wiki.compare' | translate }}

-
- Live preview to + +
+ {{ 'project.wiki.livePreviewTo' | translate }}: +
+
diff --git a/src/app/shared/components/wiki/compare-section/compare-section.component.spec.ts b/src/app/shared/components/wiki/compare-section/compare-section.component.spec.ts index 45b8e8aec..2dc8dc08a 100644 --- a/src/app/shared/components/wiki/compare-section/compare-section.component.spec.ts +++ b/src/app/shared/components/wiki/compare-section/compare-section.component.spec.ts @@ -1,15 +1,16 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { provideNoopAnimations } from '@angular/platform-browser/animations'; import { WikiVersion } from '@shared/models/wiki/wiki.model'; import { CompareSectionComponent } from './compare-section.component'; import { TranslateServiceMock } from '@testing/mocks/translate.service.mock'; +import { OSFTestingModule } from '@testing/osf.testing.module'; describe('CompareSectionComponent', () => { let component: CompareSectionComponent; let fixture: ComponentFixture; + let translateServiceMock: any; const mockVersions: WikiVersion[] = [ { @@ -22,6 +23,11 @@ describe('CompareSectionComponent', () => { createdAt: '2024-01-02T10:00:00Z', createdBy: 'Jane Smith', }, + { + id: 'version-3', + createdAt: '2024-01-03T10:00:00Z', + createdBy: 'Bob Johnson', + }, ]; const mockVersionContent = 'Original content'; @@ -29,10 +35,13 @@ describe('CompareSectionComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [CompareSectionComponent], - providers: [TranslateServiceMock, provideNoopAnimations()], + imports: [CompareSectionComponent, OSFTestingModule], + providers: [TranslateServiceMock], }).compileComponents(); + translateServiceMock = TestBed.inject(TranslateServiceMock.provide); + translateServiceMock.instant.mockReturnValue('Current'); + fixture = TestBed.createComponent(CompareSectionComponent); component = fixture.componentInstance; @@ -40,14 +49,9 @@ describe('CompareSectionComponent', () => { fixture.componentRef.setInput('versionContent', mockVersionContent); fixture.componentRef.setInput('previewContent', mockPreviewContent); fixture.componentRef.setInput('isLoading', false); - fixture.detectChanges(); }); - it('should create', () => { - expect(component).toBeTruthy(); - }); - it('should set versions input', () => { expect(component.versions()).toEqual(mockVersions); }); @@ -64,14 +68,60 @@ describe('CompareSectionComponent', () => { expect(component.isLoading()).toBe(false); }); - it('should emit selectVersion when version changes', () => { + it('should handle empty versions array', () => { + fixture.componentRef.setInput('versions', []); + fixture.detectChanges(); + + expect(component.versions()).toEqual([]); + expect(component.selectedVersion).toBeUndefined(); + }); + + it('should initialize with first version selected and emit selectVersion', () => { + expect(component.selectedVersion).toBe(mockVersions[0].id); + }); + + it('should not emit when no versions available', () => { const emitSpy = jest.spyOn(component.selectVersion, 'emit'); - const versionId = 'version-2'; - component.onVersionChange(versionId); + fixture.componentRef.setInput('versions', []); + fixture.detectChanges(); - expect(component.selectedVersion).toBe(versionId); - expect(emitSpy).toHaveBeenCalledWith(versionId); + expect(component.selectedVersion).toBeUndefined(); + expect(emitSpy).not.toHaveBeenCalled(); + }); + + it('should map versions correctly', () => { + const mappedVersions = component.mappedVersions(); + + expect(mappedVersions).toHaveLength(3); + expect(mappedVersions[0].value).toBe('version-1'); + expect(mappedVersions[0].label).toContain('(Current)'); + expect(mappedVersions[0].label).toContain('John Doe'); + expect(mappedVersions[1].value).toBe('version-2'); + expect(mappedVersions[1].label).toContain('(2)'); + expect(mappedVersions[1].label).toContain('Jane Smith'); + expect(mappedVersions[2].value).toBe('version-3'); + expect(mappedVersions[2].label).toContain('(1)'); + expect(mappedVersions[2].label).toContain('Bob Johnson'); + }); + + it('should handle version with undefined createdBy', () => { + const versionsWithUndefinedCreator: WikiVersion[] = [ + { + id: 'version-1', + createdAt: '2024-01-01T10:00:00Z', + createdBy: undefined, + }, + ]; + + fixture.componentRef.setInput('versions', versionsWithUndefinedCreator); + fixture.detectChanges(); + + const mappedVersions = component.mappedVersions(); + expect(mappedVersions).toHaveLength(1); + expect(mappedVersions[0].value).toBe('version-1'); + expect(mappedVersions[0].label).toContain('(Current)'); + expect(mappedVersions[0].label).toContain('1/1/2024'); }); it('should handle single version', () => { @@ -84,7 +134,61 @@ describe('CompareSectionComponent', () => { expect(mappedVersions[0].label).toContain('(Current)'); }); - it('should initialize with first version selected', () => { - expect(component.selectedVersion).toBe(mockVersions[0].id); + it('should compute content diff correctly', () => { + const content = component.content(); + + expect(content).toContain('Original'); + expect(content).toContain('Updated'); + expect(content).toContain('content'); + expect(content).toContain('with changes'); + }); + + it('should handle identical content', () => { + fixture.componentRef.setInput('previewContent', mockVersionContent); + fixture.detectChanges(); + + const content = component.content(); + expect(content).toBe(mockVersionContent); + }); + + it('should handle empty version content', () => { + fixture.componentRef.setInput('versionContent', ''); + fixture.detectChanges(); + + const content = component.content(); + expect(content).toContain('Updated content with changes'); + }); + + it('should handle empty preview content', () => { + fixture.componentRef.setInput('previewContent', ''); + fixture.detectChanges(); + + const content = component.content(); + expect(content).toContain('Original content'); + }); + + it('should update selectedVersion and emit selectVersion', () => { + const emitSpy = jest.spyOn(component.selectVersion, 'emit'); + const versionId = 'version-2'; + + component.onVersionChange(versionId); + + expect(component.selectedVersion).toBe(versionId); + expect(emitSpy).toHaveBeenCalledWith(versionId); + expect(emitSpy).toHaveBeenCalledTimes(1); + }); + + it('should emit correct version id when called multiple times', () => { + const emitSpy = jest.spyOn(component.selectVersion, 'emit'); + + component.onVersionChange('version-2'); + component.onVersionChange('version-3'); + component.onVersionChange('version-1'); + + expect(component.selectedVersion).toBe('version-1'); + expect(emitSpy).toHaveBeenCalledTimes(3); + expect(emitSpy).toHaveBeenNthCalledWith(1, 'version-2'); + expect(emitSpy).toHaveBeenNthCalledWith(2, 'version-3'); + expect(emitSpy).toHaveBeenNthCalledWith(3, 'version-1'); }); }); diff --git a/src/app/shared/components/wiki/compare-section/compare-section.component.ts b/src/app/shared/components/wiki/compare-section/compare-section.component.ts index 6142ba17d..a260942d7 100644 --- a/src/app/shared/components/wiki/compare-section/compare-section.component.ts +++ b/src/app/shared/components/wiki/compare-section/compare-section.component.ts @@ -1,10 +1,10 @@ -import { TranslatePipe } from '@ngx-translate/core'; +import { TranslatePipe, TranslateService } from '@ngx-translate/core'; import { Panel } from 'primeng/panel'; import { Select } from 'primeng/select'; import { Skeleton } from 'primeng/skeleton'; -import { ChangeDetectionStrategy, Component, computed, effect, input, output } from '@angular/core'; +import { ChangeDetectionStrategy, Component, computed, effect, inject, input, output } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { WikiVersion } from '@osf/shared/models/wiki/wiki.model'; @@ -25,20 +25,23 @@ export class CompareSectionComponent { isLoading = input.required(); selectVersion = output(); + translateService = inject(TranslateService); + selectedVersion: string | null = null; + private readonly currentLabel = this.translateService.instant('project.wiki.version.current'); + private readonly unknownAuthorLabel = this.translateService.instant('project.wiki.version.unknownAuthor'); + mappedVersions = computed(() => [ - ...this.versions().map((version, index) => { - const labelPrefix = index === 0 ? '(Current)' : `(${this.versions().length - index})`; - return { - label: `${labelPrefix} ${version.createdBy}: (${new Date(version.createdAt).toLocaleString()})`, - value: version.id, - }; - }), + ...this.versions().map((version, index) => ({ + label: this.formatVersionLabel(version, index), + value: version.id, + })), ]); content = computed(() => { const changes = Diff.diffWords(this.versionContent(), this.previewContent()); + return changes .map((change) => { if (change.added) { @@ -54,13 +57,21 @@ export class CompareSectionComponent { constructor() { effect(() => { this.selectedVersion = this.versions()[0]?.id; + if (this.selectedVersion) { this.selectVersion.emit(this.selectedVersion); } }); } + onVersionChange(versionId: string): void { this.selectedVersion = versionId; this.selectVersion.emit(versionId); } + + private formatVersionLabel(version: WikiVersion, index: number): string { + const prefix = index === 0 ? `(${this.currentLabel})` : `(${this.versions().length - index})`; + const creator = version.createdBy || this.unknownAuthorLabel; + return `${prefix} ${creator}: (${new Date(version.createdAt).toLocaleString()})`; + } } diff --git a/src/app/shared/components/wiki/view-section/view-section.component.html b/src/app/shared/components/wiki/view-section/view-section.component.html index 9f35cc2b5..9c6fee8c4 100644 --- a/src/app/shared/components/wiki/view-section/view-section.component.html +++ b/src/app/shared/components/wiki/view-section/view-section.component.html @@ -8,17 +8,20 @@

{{ 'project.wiki.view' | translate }}

+
{{ 'project.wiki.version.title' | translate }}: +
+
@if (content()) { diff --git a/src/app/shared/components/wiki/view-section/view-section.component.spec.ts b/src/app/shared/components/wiki/view-section/view-section.component.spec.ts index 7b8efd281..a7988daea 100644 --- a/src/app/shared/components/wiki/view-section/view-section.component.spec.ts +++ b/src/app/shared/components/wiki/view-section/view-section.component.spec.ts @@ -1,7 +1,6 @@ import { MockComponent } from 'ng-mocks'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { provideNoopAnimations } from '@angular/platform-browser/animations'; import { WikiVersion } from '@shared/models/wiki/wiki.model'; @@ -10,6 +9,7 @@ import { MarkdownComponent } from '../../markdown/markdown.component'; import { ViewSectionComponent } from './view-section.component'; import { TranslateServiceMock } from '@testing/mocks/translate.service.mock'; +import { OSFTestingModule } from '@testing/osf.testing.module'; describe('ViewSectionComponent', () => { let component: ViewSectionComponent; @@ -33,8 +33,8 @@ describe('ViewSectionComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [ViewSectionComponent, MockComponent(MarkdownComponent)], - providers: [TranslateServiceMock, provideNoopAnimations()], + imports: [ViewSectionComponent, OSFTestingModule, MockComponent(MarkdownComponent)], + providers: [TranslateServiceMock], }).compileComponents(); fixture = TestBed.createComponent(ViewSectionComponent); @@ -105,10 +105,7 @@ describe('ViewSectionComponent', () => { const mappedVersions = component.mappedVersions(); expect(mappedVersions).toHaveLength(1); - expect(mappedVersions[0]).toEqual({ - label: 'Preview', - value: null, - }); + expect(mappedVersions[0].value).toBeNull(); }); it('should handle single version', () => { @@ -118,28 +115,8 @@ describe('ViewSectionComponent', () => { const mappedVersions = component.mappedVersions(); expect(mappedVersions).toHaveLength(2); - expect(mappedVersions[0].label).toBe('Preview'); - expect(mappedVersions[1].label).toContain('(Current)'); - }); - - it('should render loading skeleton when isLoading is true', () => { - fixture.componentRef.setInput('isLoading', true); - fixture.detectChanges(); - - const compiled = fixture.nativeElement; - const skeletons = compiled.querySelectorAll('p-skeleton'); - - expect(skeletons.length).toBeGreaterThan(0); - }); - - it('should render view panel when not loading', () => { - fixture.componentRef.setInput('isLoading', false); - fixture.detectChanges(); - - const compiled = fixture.nativeElement; - const panels = compiled.querySelectorAll('p-panel'); - - expect(panels.length).toBeGreaterThan(0); + expect(mappedVersions[0].value).toBeNull(); + expect(mappedVersions[1].value).toBe('version-1'); }); it('should initialize with null selected version when not viewOnly', () => { @@ -166,25 +143,4 @@ describe('ViewSectionComponent', () => { expect(component.selectedVersion()).toBe(null); expect(emitSpy).toHaveBeenCalledWith(undefined); }); - - it('should render markdown component when content exists', () => { - fixture.componentRef.setInput('previewContent', 'Some content'); - fixture.detectChanges(); - - const compiled = fixture.nativeElement; - const markdownComponent = compiled.querySelector('osf-markdown'); - - expect(markdownComponent).toBeTruthy(); - }); - - it('should render no content message when content is empty', () => { - fixture.componentRef.setInput('previewContent', ''); - fixture.componentRef.setInput('versionContent', ''); - fixture.detectChanges(); - - const compiled = fixture.nativeElement; - const noContentMessage = compiled.querySelector('p.font-italic'); - - expect(noContentMessage).toBeTruthy(); - }); }); diff --git a/src/app/shared/components/wiki/view-section/view-section.component.ts b/src/app/shared/components/wiki/view-section/view-section.component.ts index 1be0f88e9..609d4f7dd 100644 --- a/src/app/shared/components/wiki/view-section/view-section.component.ts +++ b/src/app/shared/components/wiki/view-section/view-section.component.ts @@ -1,10 +1,10 @@ -import { TranslatePipe } from '@ngx-translate/core'; +import { TranslatePipe, TranslateService } from '@ngx-translate/core'; import { Panel } from 'primeng/panel'; import { Select } from 'primeng/select'; import { Skeleton } from 'primeng/skeleton'; -import { ChangeDetectionStrategy, Component, computed, effect, input, output, signal } from '@angular/core'; +import { ChangeDetectionStrategy, Component, computed, effect, inject, input, output, signal } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { WikiVersion } from '@osf/shared/models/wiki/wiki.model'; @@ -26,25 +26,22 @@ export class ViewSectionComponent { versionContent = input.required(); selectVersion = output(); - previewOption = { - label: 'Preview', - value: null, - }; + translateService = inject(TranslateService); selectedVersion = signal(null); content = computed(() => (this.selectedVersion() === null ? this.previewContent() : this.versionContent())); - mappedVersions = computed(() => [ - this.previewOption, - ...this.versions().map((version, index) => { - const labelPrefix = index === 0 ? '(Current)' : `(${this.versions().length - index})`; + private readonly previewLabel = this.translateService.instant('project.wiki.version.preview'); + private readonly currentLabel = this.translateService.instant('project.wiki.version.current'); + private readonly unknownAuthorLabel = this.translateService.instant('project.wiki.version.unknownAuthor'); - return { - label: `${labelPrefix} ${version.createdBy}: (${new Date(version.createdAt).toLocaleString()})`, - value: version.id, - }; - }), + mappedVersions = computed(() => [ + { label: this.previewLabel, value: null }, + ...this.versions().map((version, index) => ({ + label: this.formatVersionLabel(version, index), + value: version.id, + })), ]); constructor() { @@ -59,10 +56,17 @@ export class ViewSectionComponent { }); } - onVersionChange(versionId: string): void { + onVersionChange(versionId: string | null): void { this.selectedVersion.set(versionId); + if (versionId) { this.selectVersion.emit(versionId); } } + + private formatVersionLabel(version: WikiVersion, index: number): string { + const prefix = index === 0 ? `(${this.currentLabel})` : `(${this.versions().length - index})`; + const creator = version.createdBy || this.unknownAuthorLabel; + return `${prefix} ${creator}: (${new Date(version.createdAt).toLocaleString()})`; + } } diff --git a/src/app/shared/components/wiki/wiki-list/wiki-list.component.html b/src/app/shared/components/wiki/wiki-list/wiki-list.component.html index 41f09c1c1..d35962419 100644 --- a/src/app/shared/components/wiki/wiki-list/wiki-list.component.html +++ b/src/app/shared/components/wiki/wiki-list/wiki-list.component.html @@ -68,14 +68,15 @@

{{ item.label | translate }}

{{ item.label }}
- - + @if (canEditName(item)) { + + }
} } diff --git a/src/app/shared/components/wiki/wiki-list/wiki-list.component.scss b/src/app/shared/components/wiki/wiki-list/wiki-list.component.scss index 74bdcf60c..5c2f58375 100644 --- a/src/app/shared/components/wiki/wiki-list/wiki-list.component.scss +++ b/src/app/shared/components/wiki/wiki-list/wiki-list.component.scss @@ -2,9 +2,7 @@ display: flex; } -.wiki-list { - &-expanded { - min-width: 300px; - width: 300px; - } +.wiki-list-expanded { + min-width: 300px; + width: 300px; } diff --git a/src/app/shared/components/wiki/wiki-list/wiki-list.component.spec.ts b/src/app/shared/components/wiki/wiki-list/wiki-list.component.spec.ts index 847a87c59..818a3a412 100644 --- a/src/app/shared/components/wiki/wiki-list/wiki-list.component.spec.ts +++ b/src/app/shared/components/wiki/wiki-list/wiki-list.component.spec.ts @@ -1,24 +1,25 @@ import { MockProvider } from 'ng-mocks'; +import { MenuItem } from 'primeng/api'; + import { ComponentFixture, TestBed } from '@angular/core/testing'; import { Router } from '@angular/router'; +import { WikiModel } from '@osf/shared/models/wiki/wiki.model'; +import { WikiItemType } from '@osf/shared/models/wiki/wiki-type.model'; import { CustomConfirmationService } from '@osf/shared/services/custom-confirmation.service'; import { CustomDialogService } from '@osf/shared/services/custom-dialog.service'; -import { ComponentWiki, WikiModel } from '@shared/models/wiki/wiki.model'; -import { WikiItemType } from '@shared/models/wiki/wiki-type.model'; +import { ComponentWiki } from '@osf/shared/stores/wiki'; import { WikiListComponent } from './wiki-list.component'; import { OSFTestingModule } from '@testing/osf.testing.module'; import { CustomConfirmationServiceMockBuilder } from '@testing/providers/custom-confirmation-provider.mock'; -import { DialogServiceMockBuilder } from '@testing/providers/dialog-provider.mock'; import { RouterMockBuilder } from '@testing/providers/router-provider.mock'; describe('WikiListComponent', () => { let component: WikiListComponent; let fixture: ComponentFixture; - let mockCustomDialogService: ReturnType; let mockCustomConfirmationService: ReturnType; let mockRouter: ReturnType; @@ -42,14 +43,13 @@ describe('WikiListComponent', () => { ]; beforeEach(async () => { - mockCustomDialogService = DialogServiceMockBuilder.create().withOpenMock().build(); mockCustomConfirmationService = CustomConfirmationServiceMockBuilder.create().build(); mockRouter = RouterMockBuilder.create().withUrl('/project/abc123/wiki').build(); await TestBed.configureTestingModule({ imports: [WikiListComponent, OSFTestingModule], providers: [ - MockProvider(CustomDialogService, mockCustomDialogService), + MockProvider(CustomDialogService), MockProvider(CustomConfirmationService, mockCustomConfirmationService), MockProvider(Router, mockRouter), ], @@ -153,6 +153,52 @@ describe('WikiListComponent', () => { expect(component.isHomeWikiSelected()).toBe(false); }); + it('should compute homeWikiId correctly', () => { + fixture.componentRef.setInput('list', mockWikiList); + fixture.componentRef.setInput('resourceId', 'resource-123'); + fixture.componentRef.setInput('currentWikiId', 'wiki1'); + fixture.componentRef.setInput('componentsList', []); + fixture.detectChanges(); + + expect(component.homeWikiId()).toBe('wiki1'); + }); + + it('should return true for canEditName when user can edit and item is not home', () => { + fixture.componentRef.setInput('list', mockWikiList); + fixture.componentRef.setInput('resourceId', 'resource-123'); + fixture.componentRef.setInput('currentWikiId', 'wiki1'); + fixture.componentRef.setInput('componentsList', []); + fixture.componentRef.setInput('canEdit', true); + fixture.detectChanges(); + + const nonHomeItem = { id: 'wiki2' } as MenuItem; + expect(component.canEditName(nonHomeItem)).toBe(true); + }); + + it('should return false for canEditName when item is home wiki', () => { + fixture.componentRef.setInput('list', mockWikiList); + fixture.componentRef.setInput('resourceId', 'resource-123'); + fixture.componentRef.setInput('currentWikiId', 'wiki1'); + fixture.componentRef.setInput('componentsList', []); + fixture.componentRef.setInput('canEdit', true); + fixture.detectChanges(); + + const homeItem = { id: 'wiki1' } as MenuItem; + expect(component.canEditName(homeItem)).toBe(false); + }); + + it('should return false for canEditName when user cannot edit', () => { + fixture.componentRef.setInput('list', mockWikiList); + fixture.componentRef.setInput('resourceId', 'resource-123'); + fixture.componentRef.setInput('currentWikiId', 'wiki1'); + fixture.componentRef.setInput('componentsList', []); + fixture.componentRef.setInput('canEdit', false); + fixture.detectChanges(); + + const nonHomeItem = { id: 'wiki2' } as MenuItem; + expect(component.canEditName(nonHomeItem)).toBe(false); + }); + it('should compute wikiMenu with main wikis', () => { fixture.componentRef.setInput('list', mockWikiList); fixture.componentRef.setInput('resourceId', 'resource-123'); diff --git a/src/app/shared/components/wiki/wiki-list/wiki-list.component.ts b/src/app/shared/components/wiki/wiki-list/wiki-list.component.ts index 97f1b7baa..d353a9893 100644 --- a/src/app/shared/components/wiki/wiki-list/wiki-list.component.ts +++ b/src/app/shared/components/wiki/wiki-list/wiki-list.component.ts @@ -1,11 +1,13 @@ import { TranslatePipe } from '@ngx-translate/core'; +import { MenuItem } from 'primeng/api'; import { Button } from 'primeng/button'; import { Panel } from 'primeng/panel'; import { PanelMenu } from 'primeng/panelmenu'; import { Skeleton } from 'primeng/skeleton'; -import { ChangeDetectionStrategy, Component, computed, inject, input, output, signal } from '@angular/core'; +import { ChangeDetectionStrategy, Component, computed, DestroyRef, inject, input, output, signal } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { Router } from '@angular/router'; import { WikiModel } from '@osf/shared/models/wiki/wiki.model'; @@ -14,9 +16,9 @@ import { WikiItemType } from '@osf/shared/models/wiki/wiki-type.model'; import { CustomConfirmationService } from '@osf/shared/services/custom-confirmation.service'; import { CustomDialogService } from '@osf/shared/services/custom-dialog.service'; import { ComponentWiki } from '@osf/shared/stores/wiki'; -import { RenameWikiDialogComponent } from '@shared/components/wiki/rename-wiki-dialog/rename-wiki-dialog.component'; import { AddWikiDialogComponent } from '../add-wiki-dialog/add-wiki-dialog.component'; +import { RenameWikiDialogComponent } from '../rename-wiki-dialog/rename-wiki-dialog.component'; @Component({ selector: 'osf-wiki-list', @@ -41,16 +43,14 @@ export class WikiListComponent { private readonly customDialogService = inject(CustomDialogService); private readonly customConfirmationService = inject(CustomConfirmationService); private readonly router = inject(Router); + private readonly destroyRef = inject(DestroyRef); wikiItemType = WikiItemType; expanded = signal(true); hasComponentsWikis = computed(() => this.componentsList().length > 0); - - isHomeWikiSelected = computed(() => { - const homeWikiId = this.list()?.find((wiki) => wiki.name.toLowerCase() === 'home')?.id; - return this.currentWikiId() === homeWikiId; - }); + homeWikiId = computed(() => this.list()?.find((wiki) => wiki.name.toLowerCase() === 'home')?.id); + isHomeWikiSelected = computed(() => this.currentWikiId() === this.homeWikiId()); wikiMenu = computed(() => { const menu: WikiMenuItem[] = [ @@ -96,7 +96,8 @@ export class WikiListComponent { resourceId: this.resourceId(), }, }) - .onClose.subscribe(() => this.createWiki.emit()); + .onClose.pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe(() => this.createWiki.emit()); } openRenameWikiDialog(wikiId: string, wikiName: string) { @@ -109,7 +110,8 @@ export class WikiListComponent { wikiName: wikiName, }, }) - .onClose.subscribe(() => this.renameWiki.emit()); + .onClose.pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe(() => this.renameWiki.emit()); } openDeleteWikiDialog(): void { @@ -124,6 +126,10 @@ export class WikiListComponent { this.expanded.update((value) => !value); } + canEditName(item: MenuItem): boolean { + return this.canEdit() && item.id !== this.homeWikiId(); + } + private navigateTo(wikiId: string, componentId?: string) { if (componentId) { this.router.navigateByUrl('/').then(() => { diff --git a/src/app/shared/mappers/wiki/wiki.mapper.ts b/src/app/shared/mappers/wiki/wiki.mapper.ts index 8d16aaedb..63b8a7f73 100644 --- a/src/app/shared/mappers/wiki/wiki.mapper.ts +++ b/src/app/shared/mappers/wiki/wiki.mapper.ts @@ -16,10 +16,6 @@ import { replaceBadEncodedChars } from '@shared/helpers/format-bad-encoding.help export class WikiMapper { private static translate: TranslateService; - static init(translate: TranslateService): void { - WikiMapper.translate = translate; - } - static fromCreateWikiResponse(response: WikiGetResponse): WikiModel { return { id: response.id, @@ -57,9 +53,7 @@ export class WikiMapper { return { id: response.id, createdAt: response.attributes.date_created, - createdBy: - UserMapper.getUserInfo(response.embeds.user)?.fullName || - WikiMapper.translate.instant('project.wiki.version.unknownAuthor'), + createdBy: UserMapper.getUserInfo(response.embeds.user)?.fullName, }; } diff --git a/src/app/shared/models/wiki/wiki.model.ts b/src/app/shared/models/wiki/wiki.model.ts index d868fc993..13b17ce67 100644 --- a/src/app/shared/models/wiki/wiki.model.ts +++ b/src/app/shared/models/wiki/wiki.model.ts @@ -22,7 +22,7 @@ export interface WikisWithMeta { export interface WikiVersion { id: string; createdAt: string; - createdBy: string; + createdBy: string | undefined; } export interface ComponentWiki { diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 4e1eafd6c..bec1308dc 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -925,6 +925,7 @@ "horizontalRule": "Horizontal rule", "redo": "Redo", "undo": "Undo", + "livePreviewTo": "Live preview to", "version": { "title": "Version", "preview": "Preview",