diff --git a/packages/web-app-files/src/components/FilesList/ListHeader.vue b/packages/web-app-files/src/components/FilesList/ListHeader.vue new file mode 100644 index 0000000000..c521c84614 --- /dev/null +++ b/packages/web-app-files/src/components/FilesList/ListHeader.vue @@ -0,0 +1,106 @@ + + + + + + + + + + + {{ toggleMarkdownCollapsedText }} + + + + + + diff --git a/packages/web-app-files/src/views/spaces/GenericSpace.vue b/packages/web-app-files/src/views/spaces/GenericSpace.vue index 09f5298953..50d0bf9de8 100644 --- a/packages/web-app-files/src/views/spaces/GenericSpace.vue +++ b/packages/web-app-files/src/views/spaces/GenericSpace.vue @@ -52,6 +52,12 @@ + { + return unref(resourcesViewDefaults.storeItems).find( + (item) => item.name.toLowerCase() === 'readme.md' + ) + }) + onMounted(() => { performLoaderTask(false) loadResourcesEventToken = eventBus.subscribe( @@ -570,7 +584,8 @@ export default defineComponent({ totalResourcesCount, areHiddenFilesShown, fileDropped, - loadPreview + loadPreview, + readmeFile } }, diff --git a/packages/web-app-files/tests/unit/components/FilesList/ListHeader.spec.ts b/packages/web-app-files/tests/unit/components/FilesList/ListHeader.spec.ts new file mode 100644 index 0000000000..ac4920325c --- /dev/null +++ b/packages/web-app-files/tests/unit/components/FilesList/ListHeader.spec.ts @@ -0,0 +1,39 @@ +import ListHeader from '../../../../src/components/FilesList/ListHeader.vue' +import { defaultComponentMocks, defaultPlugins, shallowMount } from '@opencloud-eu/web-test-helpers' +import { mock } from 'vitest-mock-extended' +import { Resource, SpaceResource } from '@opencloud-eu/web-client' +import { flushPromises } from '@vue/test-utils' + +describe('ListHeader', () => { + it('renders a spinner when loading', () => { + const wrapper = getWrapper() + expect(wrapper.find('oc-spinner-stub').exists()).toBeTruthy() + }) + it('renders a markdown container when README content is loaded', async () => { + const wrapper = getWrapper() + await flushPromises() + expect(wrapper.find('.markdown-container').exists()).toBeTruthy() + }) +}) + +function getWrapper() { + const mocks = { + ...defaultComponentMocks() + } + + mocks.$clientService.webdav.getFileContents.mockResolvedValueOnce({ + body: 'Sample README content' + }) + + return shallowMount(ListHeader, { + props: { + space: mock(), + readmeFile: mock() + }, + global: { + mocks, + plugins: [...defaultPlugins()], + provide: mocks + } + }) +} diff --git a/packages/web-app-files/tests/unit/views/spaces/GenericSpace.spec.ts b/packages/web-app-files/tests/unit/views/spaces/GenericSpace.spec.ts index f967dbfcba..55dc281fd9 100644 --- a/packages/web-app-files/tests/unit/views/spaces/GenericSpace.spec.ts +++ b/packages/web-app-files/tests/unit/views/spaces/GenericSpace.spec.ts @@ -81,7 +81,7 @@ describe('GenericSpace view', () => { expect(wrapper.find('.no-content-message').exists()).toBeTruthy() }) it('shows the files table when files are available', () => { - const { wrapper } = getMountedWrapper({ files: [mock()] }) + const { wrapper } = getMountedWrapper({ files: [mock({ name: 'file.txt' })] }) expect(wrapper.find('.no-content-message').exists()).toBeFalsy() expect(wrapper.find('resource-table-stub').exists()).toBeTruthy() }) @@ -175,7 +175,7 @@ describe('GenericSpace view', () => { it('renders the ResourceDetails component if no currentFolder id is present', () => { const { wrapper } = getMountedWrapper({ currentFolder: mock({ fileId: '' }), - files: [mock({ isFolder: false })], + files: [mock({ name: 'file.txt', isFolder: false })], runningOnEos: true }) expect(wrapper.find('resource-details-stub').exists()).toBeTruthy() @@ -187,7 +187,7 @@ describe('GenericSpace view', () => { ...mock(), path }, - files: [{ ...mock(), path }], + files: [{ ...mock({ name: 'file.txt' }), path }], runningOnEos: true }) expect(wrapper.find('resource-details-stub').exists()).toBeTruthy() @@ -199,7 +199,7 @@ describe('GenericSpace view', () => { currentFolder: { ...mock() }, - files: [{ ...mock(), isFolder: false }], + files: [{ ...mock({ name: 'file.txt' }), isFolder: false }], space: mock({ id: '1', getDriveAliasAndItem: vi.fn(), @@ -230,6 +230,23 @@ describe('GenericSpace view', () => { expect(wrapper.find(selectors.actionsCreateAndUpload).exists()).toBe(true) }) }) + describe('list header', () => { + it('renders when a readme file is present', () => { + const { wrapper } = getMountedWrapper({ files: [mock({ name: 'readme.md' })] }) + expect(wrapper.find('list-header-stub').exists()).toBeTruthy() + }) + it('does not render when a readme file is not present', () => { + const { wrapper } = getMountedWrapper({ files: [mock({ name: 'file.txt' })] }) + expect(wrapper.find('list-header-stub').exists()).toBeFalsy() + }) + it('does not render on the frontpage of a space', () => { + const { wrapper } = getMountedWrapper({ + files: [mock({ name: 'readme.md' })], + space: mock({ driveType: 'project' }) + }) + expect(wrapper.find('list-header-stub').exists()).toBeFalsy() + }) + }) }) function getMountedWrapper({ @@ -269,7 +286,8 @@ function getMountedWrapper({ const resourcesViewDetailsMock = useResourcesViewDefaultsMock({ paginatedResources: ref(files), - areResourcesLoading: ref(loading) + areResourcesLoading: ref(loading), + storeItems: ref(files) }) vi.mocked(useResourcesViewDefaults).mockImplementation(() => resourcesViewDetailsMock) vi.mocked(useBreadcrumbsFromPath).mockImplementation(() => @@ -296,7 +314,13 @@ function getMountedWrapper({ plugins, mocks: defaultMocks, provide: defaultMocks, - stubs: { ...defaultStubs, 'resource-details': true, portal: true, ...stubs } + stubs: { + ...defaultStubs, + 'resource-details': true, + portal: true, + ...stubs, + ListHeader: true + } } }) } diff --git a/packages/web-pkg/src/components/TextEditor/TextEditor.vue b/packages/web-pkg/src/components/TextEditor/TextEditor.vue index 79d667a37f..1d8eef4930 100644 --- a/packages/web-pkg/src/components/TextEditor/TextEditor.vue +++ b/packages/web-pkg/src/components/TextEditor/TextEditor.vue @@ -3,21 +3,22 @@ id="text-editor-container" class="h-full [&_.md-editor-preview]:!font-(family-name:--oc-font-family)" > - + + + :first-child, +#text-editor-preview-component-preview > :first-child { + margin-top: 0 !important; +} + // overwrite md-editor styles .md-editor { height: 100%;