fix: render newsfeed content as html
This commit is contained in:
@@ -23,7 +23,7 @@ import {
|
||||
} from '@cio/utils/validation/newsfeed';
|
||||
|
||||
import { get } from 'svelte/store';
|
||||
import { getTextFromHTML } from '$lib/utils/functions/toHtml';
|
||||
import { isHtmlValueEmpty } from '$lib/utils/functions/toHtml';
|
||||
import { mapZodErrorsToTranslations } from '$lib/utils/validation';
|
||||
import { profile } from '$lib/utils/store/user';
|
||||
import { snackbar } from '$features/ui/snackbar/store';
|
||||
@@ -109,7 +109,15 @@ export class NewsfeedApi extends BaseApiWithErrors {
|
||||
* Creates a new newsfeed item
|
||||
*/
|
||||
async create(courseId: string, fields: TNewsfeedCreate) {
|
||||
const result = ZNewsfeedCreate.safeParse({ ...fields, content: getTextFromHTML(fields.content), courseId });
|
||||
if (isHtmlValueEmpty(fields.content)) {
|
||||
this.errors = mapZodErrorsToTranslations(
|
||||
ZNewsfeedCreate.safeParse({ ...fields, content: '', courseId }).error!,
|
||||
'newsfeed'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const result = ZNewsfeedCreate.safeParse({ ...fields, courseId });
|
||||
if (!result.success) {
|
||||
this.errors = mapZodErrorsToTranslations(result.error, 'newsfeed');
|
||||
return;
|
||||
@@ -160,10 +168,15 @@ export class NewsfeedApi extends BaseApiWithErrors {
|
||||
* Updates a newsfeed item (content and isPinned only)
|
||||
*/
|
||||
async update(courseId: string, feedId: string, fields: TNewsfeedUpdate) {
|
||||
const result = ZNewsfeedUpdate.safeParse({
|
||||
...fields,
|
||||
content: getTextFromHTML(fields.content ?? '')
|
||||
});
|
||||
if (fields.content !== undefined && isHtmlValueEmpty(fields.content)) {
|
||||
this.errors = mapZodErrorsToTranslations(
|
||||
ZNewsfeedUpdate.safeParse({ ...fields, content: '' }).error!,
|
||||
'newsfeed'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const result = ZNewsfeedUpdate.safeParse(fields);
|
||||
|
||||
if (!result.success) {
|
||||
this.errors = mapZodErrorsToTranslations(result.error, 'newsfeed');
|
||||
|
||||
@@ -24,7 +24,7 @@ import {
|
||||
ZUpdateProgramReaction
|
||||
} from '@cio/utils/validation/program';
|
||||
import { get } from 'svelte/store';
|
||||
import { getTextFromHTML } from '$lib/utils/functions/toHtml';
|
||||
import { isHtmlValueEmpty } from '$lib/utils/functions/toHtml';
|
||||
import { mapZodErrorsToTranslations } from '$lib/utils/validation';
|
||||
import { profile } from '$lib/utils/store/user';
|
||||
import { snackbar } from '$features/ui/snackbar/store';
|
||||
@@ -77,10 +77,15 @@ export class ProgramNewsfeedApi extends BaseApiWithErrors {
|
||||
async create(programId: string, fields: TCreateProgramNewsfeed) {
|
||||
this.success = false;
|
||||
|
||||
const validationResult = ZCreateProgramNewsfeed.safeParse({
|
||||
...fields,
|
||||
content: getTextFromHTML(fields.content)
|
||||
});
|
||||
if (isHtmlValueEmpty(fields.content)) {
|
||||
this.errors = mapZodErrorsToTranslations(
|
||||
ZCreateProgramNewsfeed.safeParse({ ...fields, content: '' }).error!,
|
||||
'newsfeed'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const validationResult = ZCreateProgramNewsfeed.safeParse(fields);
|
||||
|
||||
if (!validationResult.success) {
|
||||
this.errors = mapZodErrorsToTranslations(validationResult.error, 'newsfeed');
|
||||
@@ -115,10 +120,15 @@ export class ProgramNewsfeedApi extends BaseApiWithErrors {
|
||||
async update(programId: string, feedId: string, fields: TUpdateProgramNewsfeed) {
|
||||
this.success = false;
|
||||
|
||||
const validationResult = ZUpdateProgramNewsfeed.safeParse({
|
||||
...fields,
|
||||
...(fields.content ? { content: getTextFromHTML(fields.content) } : {})
|
||||
});
|
||||
if (fields.content !== undefined && isHtmlValueEmpty(fields.content)) {
|
||||
this.errors = mapZodErrorsToTranslations(
|
||||
ZUpdateProgramNewsfeed.safeParse({ ...fields, content: '' }).error!,
|
||||
'newsfeed'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const validationResult = ZUpdateProgramNewsfeed.safeParse(fields);
|
||||
|
||||
if (!validationResult.success) {
|
||||
this.errors = mapZodErrorsToTranslations(validationResult.error, 'newsfeed');
|
||||
|
||||
@@ -23,6 +23,7 @@ export { default as Search } from './search.svelte';
|
||||
export { default as SenjaEmbed } from './senja-embed.svelte';
|
||||
export { default as Snackbar } from './snackbar/snackbar.svelte';
|
||||
export { default as TextEditor } from './text-editor.svelte';
|
||||
export { preloadTextEditor } from './text-editor.svelte';
|
||||
export { default as UnsavedChanges } from './unsaved-changes.svelte';
|
||||
export { default as UploadImage } from './upload-image.svelte';
|
||||
export { default as UpgradeBanner } from './upgrade-banner.svelte';
|
||||
|
||||
@@ -8,11 +8,17 @@
|
||||
pending ??= import('@cio/ui/custom/editor');
|
||||
return pending;
|
||||
}
|
||||
|
||||
/** Warm the editor chunk without mounting an instance (e.g. on newsfeed page load). */
|
||||
export function preloadTextEditor() {
|
||||
return loadEditor();
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
// Type-only imports are erased at build time — no static TipTap dependency.
|
||||
import type { HTMLContent, TiptapEditor } from '@cio/ui/custom/editor';
|
||||
import { cn } from '@cio/ui/tools';
|
||||
|
||||
interface Props {
|
||||
placeholder?: string | ((node: any) => string);
|
||||
@@ -46,7 +52,21 @@
|
||||
</script>
|
||||
|
||||
{#await loadEditor()}
|
||||
<div class="ui:animate-pulse ui:rounded-md ui:bg-muted ui:h-32 ui:w-full" />
|
||||
<div
|
||||
class={cn(
|
||||
'ui:relative ui:bg-background ui:flex ui:w-full ui:flex-col ui:rounded-md ui:border ui:border-dashed',
|
||||
className
|
||||
)}
|
||||
aria-busy="true"
|
||||
aria-hidden="true"
|
||||
>
|
||||
{#if showToolBar}
|
||||
<div class="ui:h-9 ui:shrink-0 ui:border-b ui:border-dashed ui:bg-muted/50" />
|
||||
{/if}
|
||||
<div
|
||||
class={cn('ui:relative ui:h-128 ui:w-full ui:overflow-auto ui:p-4 ui:animate-pulse ui:bg-muted/50', editorClass)}
|
||||
/>
|
||||
</div>
|
||||
{:then { Editor }}
|
||||
<Editor
|
||||
{content}
|
||||
|
||||
Reference in New Issue
Block a user