style: Apply Prettier formatting

Applied consistent code formatting across the project using Prettier, addressing minor style inconsistencies introduced in recent changes.
This commit is contained in:
Scott Idem
2025-11-18 14:25:21 -05:00
parent 691b20fd54
commit d678f97324
9 changed files with 981 additions and 946 deletions

View File

@@ -73,3 +73,14 @@ The rich text editor component, previously based on Tiptap (`shad-editor`), has
- **Wrapper Component Update:** The existing editor wrapper (`src/lib/elements/element_tiptap_editor.svelte`) was renamed to `src/lib/elements/element_codemirror_wrapper.svelte` and refactored to utilize the new CodeMirror component. Tiptap-specific logic and props were removed. - **Wrapper Component Update:** The existing editor wrapper (`src/lib/elements/element_tiptap_editor.svelte`) was renamed to `src/lib/elements/element_codemirror_wrapper.svelte` and refactored to utilize the new CodeMirror component. Tiptap-specific logic and props were removed.
- **Component Usage Updates:** All Svelte components that previously imported and used the Tiptap wrapper were updated to import `element_codemirror_wrapper.svelte`. Unsupported props such as `default_minimal`, `show_button_kv`, `bind:new_html`, and `bind:changed` were removed from their usage. - **Component Usage Updates:** All Svelte components that previously imported and used the Tiptap wrapper were updated to import `element_codemirror_wrapper.svelte`. Unsupported props such as `default_minimal`, `show_button_kv`, `bind:new_html`, and `bind:changed` were removed from their usage.
- **Dependency Cleanup:** `npm install` was run to remove unneeded packages, and `npm run format` was executed to ensure consistent code style. - **Dependency Cleanup:** `npm install` was run to remove unneeded packages, and `npm run format` was executed to ensure consistent code style.
### CodeMirror Bug Fixes (2025-11-18)
Following the initial migration to CodeMirror, several issues were identified and resolved:
- **Initialization Errors:** An "Unrecognized extension value" error was fixed by refactoring `codemirror_modules.ts` to explicitly import individual CodeMirror extensions instead of relying on the `basicSetup` bundle. This ensures proper singleton usage and prevents module duplication.
- **Text Wrapping:** The `EditorView.lineWrapping` extension was added to `element_codemirror_editor.svelte` and `e_app_codemirror_v5.svelte` to enable text wrapping.
- **Content Saving:** Content binding issues were resolved in various IDAA components by correctly binding the `html_text` prop of the CodeMirror wrapper to the corresponding state variables.
- **Save Button Enablement:** The logic for enabling the "Save" button was fixed in `ae_idaa_comp__post_obj_id_edit.svelte` to correctly detect changes in the CodeMirror editor.
- **Editor Buttons:** A `TypeError` in the editor's formatting buttons was fixed by using `EditorSelection.range()` to correctly create selection ranges.
- **Component Renaming:** The `Tiptap_editor` component alias was renamed to `CodeMirror_wrapper` across the project for clarity, and the wrapper file was renamed to `element_codemirror_editor_wrapper.svelte`.

View File

@@ -49,7 +49,7 @@ This is a list of tasks to be completed before the next event/show/conference.
### 2. Component Standardization ### 2. Component Standardization
- [ ] **CodeMirror Migration:** Plan and execute the replacement of the `shad-editor` and potentially other text editors (like Tiptap) with `CodeMirror` to standardize rich text editing. - [x] **CodeMirror Migration:** Replaced all instances of the old Tiptap editor with a new CodeMirror wrapper. This includes fixing initialization errors, enabling text wrapping, and ensuring content is correctly saved.
- [ ] **Component Review:** Audit third-party components to understand their conventions and isolate them from internal standards. - [ ] **Component Review:** Audit third-party components to understand their conventions and isolate them from internal standards.
--- ---
@@ -83,7 +83,7 @@ These functions are frequently used and critical to the application's data flow.
--- ---
- [ ] Improve the `e_app_codemirror_v5.svelte` component and plan the migration from Tiptap to CodeMirror for rich text editing. - [x] Improve the `e_app_codemirror_v5.svelte` component and plan the migration from Tiptap to CodeMirror for rich text editing. The migration is complete, and the component has been improved to handle individual extensions and fix various bugs.
--- ---
@@ -190,7 +190,7 @@ These functions are frequently used and critical to the application's data flow.
- [ ] **UI/UX:** - [ ] **UI/UX:**
- [ ] Improve the UI for creating and editing posts and comments. - [ ] Improve the UI for creating and editing posts and comments.
- [ ] Add a rich text editor for a better writing experience. - [x] Add a rich text editor for a better writing experience.
- [ ] **Features:** - [ ] **Features:**
- [ ] Implement user-specific features, such as editing their own posts and comments. - [ ] Implement user-specific features, such as editing their own posts and comments.

View File

@@ -38,7 +38,7 @@
cm_modules = await ensureCodeMirrorModules(); cm_modules = await ensureCodeMirrorModules();
if (!cm_modules) return; if (!cm_modules) return;
// Reactive declaration for extensions // Reactive declaration for extensions
let editor_extensions = [ let editor_extensions = [
// Core extensions // Core extensions
cm_modules.highlightSpecialChars(), cm_modules.highlightSpecialChars(),
@@ -63,7 +63,10 @@
...cm_modules.completionKeymap, ...cm_modules.completionKeymap,
...cm_modules.lintKeymap ...cm_modules.lintKeymap
]), ]),
cm_modules.markdown({ base: cm_modules.markdownLanguage, codeLanguages: cm_modules.languages }), cm_modules.markdown({
base: cm_modules.markdownLanguage,
codeLanguages: cm_modules.languages
}),
theme_mode == 'dark' ? cm_modules.oneDark : cm_modules.EditorView.baseTheme(), theme_mode == 'dark' ? cm_modules.oneDark : cm_modules.EditorView.baseTheme(),
cm_modules.EditorView.contentAttributes.of({ spellcheck: 'true' }), // Enable spell check cm_modules.EditorView.contentAttributes.of({ spellcheck: 'true' }), // Enable spell check

View File

@@ -1,170 +1,170 @@
let _cmCache: { let _cmCache: {
EditorView?: any; EditorView?: any;
EditorState?: any; EditorState?: any;
basicSetup?: any; basicSetup?: any;
markdown?: any; markdown?: any;
markdownLanguage?: any; markdownLanguage?: any;
keymap?: any; keymap?: any;
defaultKeymap?: any; defaultKeymap?: any;
history?: any; history?: any;
historyKeymap?: any; historyKeymap?: any;
lineNumbers?: any; lineNumbers?: any;
highlightSpecialChars?: any; highlightSpecialChars?: any;
drawSelection?: any; drawSelection?: any;
dropCursor?: any; dropCursor?: any;
rectangularSelection?: any; rectangularSelection?: any;
crosshairCursor?: any; crosshairCursor?: any;
highlightActiveLine?: any; highlightActiveLine?: any;
highlightActiveLineGutter?: any; highlightActiveLineGutter?: any;
indentWithTab?: any; indentWithTab?: any;
indentUnit?: any; indentUnit?: any;
autocompletion?: any; autocompletion?: any;
completionKeymap?: any; completionKeymap?: any;
closeBrackets?: any; closeBrackets?: any;
closeBracketsKeymap?: any; closeBracketsKeymap?: any;
searchKeymap?: any; searchKeymap?: any;
highlightSelectionMatches?: any; highlightSelectionMatches?: any;
lintKeymap?: any; lintKeymap?: any;
EditorState_allowMultipleSelections?: any; EditorState_allowMultipleSelections?: any;
EditorView_lineWrapping?: any; EditorView_lineWrapping?: any;
EditorView_editable?: any; EditorView_editable?: any;
EditorView_contentAttributes?: any; EditorView_contentAttributes?: any;
bracketMatching?: any; bracketMatching?: any;
foldGutter?: any; foldGutter?: any;
foldKeymap?: any; foldKeymap?: any;
indentOnInput?: any; indentOnInput?: any;
languages?: any; languages?: any;
oneDark?: any; oneDark?: any;
placeholderExt?: any; placeholderExt?: any;
} | null = null; } | null = null;
// ...existing code... // ...existing code...
import { browser } from '$app/environment'; import { browser } from '$app/environment';
type CMCache = { type CMCache = {
EditorView: any; EditorView: any;
EditorState: any; EditorState: any;
basicSetup?: any; basicSetup?: any;
markdown?: any; markdown?: any;
markdownLanguage?: any; markdownLanguage?: any;
keymap?: any; keymap?: any;
defaultKeymap?: any; defaultKeymap?: any;
history?: any; history?: any;
historyKeymap?: any; historyKeymap?: any;
lineNumbers?: any; lineNumbers?: any;
highlightSpecialChars?: any; highlightSpecialChars?: any;
drawSelection?: any; drawSelection?: any;
dropCursor?: any; dropCursor?: any;
rectangularSelection?: any; rectangularSelection?: any;
crosshairCursor?: any; crosshairCursor?: any;
highlightActiveLine?: any; highlightActiveLine?: any;
highlightActiveLineGutter?: any; highlightActiveLineGutter?: any;
indentWithTab?: any; indentWithTab?: any;
indentUnit?: any; indentUnit?: any;
autocompletion?: any; autocompletion?: any;
completionKeymap?: any; completionKeymap?: any;
closeBrackets?: any; closeBrackets?: any;
closeBracketsKeymap?: any; closeBracketsKeymap?: any;
searchKeymap?: any; searchKeymap?: any;
highlightSelectionMatches?: any; highlightSelectionMatches?: any;
lintKeymap?: any; lintKeymap?: any;
EditorState_allowMultipleSelections?: any; EditorState_allowMultipleSelections?: any;
EditorView_lineWrapping?: any; EditorView_lineWrapping?: any;
EditorView_editable?: any; EditorView_editable?: any;
EditorView_contentAttributes?: any; EditorView_contentAttributes?: any;
bracketMatching?: any; bracketMatching?: any;
foldGutter?: any; foldGutter?: any;
foldKeymap?: any; foldKeymap?: any;
indentOnInput?: any; indentOnInput?: any;
languages?: any; languages?: any;
oneDark?: any; oneDark?: any;
placeholderExt?: any; placeholderExt?: any;
} | null; } | null;
const GLOBAL_KEY = '__cm_singleton_modules_v1'; const GLOBAL_KEY = '__cm_singleton_modules_v1';
export async function ensureCodeMirrorModules(): Promise<CMCache> { export async function ensureCodeMirrorModules(): Promise<CMCache> {
if (!browser) return null; if (!browser) return null;
// Use a single global object so HMR/multiple module copies reuse same instance // Use a single global object so HMR/multiple module copies reuse same instance
const globalAny = globalThis as any; const globalAny = globalThis as any;
if (globalAny[GLOBAL_KEY]) return globalAny[GLOBAL_KEY] as CMCache; if (globalAny[GLOBAL_KEY]) return globalAny[GLOBAL_KEY] as CMCache;
const [ const [
viewMod, viewMod,
stateMod, stateMod,
basicSetupMod, basicSetupMod,
markdownMod, markdownMod,
commandsMod, commandsMod,
languageMod, languageMod,
autocompleteMod, autocompleteMod,
searchMod, searchMod,
lintMod, lintMod,
themeOneDarkMod themeOneDarkMod
] = await Promise.all([ ] = await Promise.all([
import('@codemirror/view'), import('@codemirror/view'),
import('@codemirror/state'), import('@codemirror/state'),
import('@codemirror/basic-setup'), import('@codemirror/basic-setup'),
import('@codemirror/lang-markdown'), import('@codemirror/lang-markdown'),
import('@codemirror/commands'), import('@codemirror/commands'),
import('@codemirror/language'), import('@codemirror/language'),
import('@codemirror/autocomplete'), import('@codemirror/autocomplete'),
import('@codemirror/search'), import('@codemirror/search'),
import('@codemirror/lint'), import('@codemirror/lint'),
import('@codemirror/theme-one-dark') import('@codemirror/theme-one-dark')
]); ]);
const cache: CMCache = { const cache: CMCache = {
EditorView: viewMod.EditorView, EditorView: viewMod.EditorView,
keymap: viewMod.keymap, keymap: viewMod.keymap,
lineNumbers: viewMod.lineNumbers, lineNumbers: viewMod.lineNumbers,
highlightSpecialChars: viewMod.highlightSpecialChars, highlightSpecialChars: viewMod.highlightSpecialChars,
drawSelection: viewMod.drawSelection, drawSelection: viewMod.drawSelection,
dropCursor: viewMod.dropCursor, dropCursor: viewMod.dropCursor,
rectangularSelection: viewMod.rectangularSelection, rectangularSelection: viewMod.rectangularSelection,
crosshairCursor: viewMod.crosshairCursor, crosshairCursor: viewMod.crosshairCursor,
highlightActiveLine: viewMod.highlightActiveLine, highlightActiveLine: viewMod.highlightActiveLine,
highlightActiveLineGutter: viewMod.highlightActiveLineGutter, highlightActiveLineGutter: viewMod.highlightActiveLineGutter,
EditorView_lineWrapping: viewMod.EditorView.lineWrapping, EditorView_lineWrapping: viewMod.EditorView.lineWrapping,
EditorView_editable: viewMod.EditorView.editable, EditorView_editable: viewMod.EditorView.editable,
EditorView_contentAttributes: viewMod.EditorView.contentAttributes, EditorView_contentAttributes: viewMod.EditorView.contentAttributes,
placeholderExt: viewMod.placeholder, placeholderExt: viewMod.placeholder,
EditorState: stateMod.EditorState, EditorState: stateMod.EditorState,
EditorSelection: stateMod.EditorSelection, EditorSelection: stateMod.EditorSelection,
EditorState_allowMultipleSelections: stateMod.EditorState.allowMultipleSelections, EditorState_allowMultipleSelections: stateMod.EditorState.allowMultipleSelections,
EditorState_readOnly: stateMod.EditorState.readOnly, EditorState_readOnly: stateMod.EditorState.readOnly,
basicSetup: basicSetupMod?.basicSetup, basicSetup: basicSetupMod?.basicSetup,
markdown: markdownMod?.markdown, markdown: markdownMod?.markdown,
markdownLanguage: markdownMod?.markdownLanguage, markdownLanguage: markdownMod?.markdownLanguage,
languages: languageMod?.languages, // From @codemirror/language-data, often re-exported by @codemirror/language languages: languageMod?.languages, // From @codemirror/language-data, often re-exported by @codemirror/language
defaultKeymap: (commandsMod && commandsMod.defaultKeymap) || [], defaultKeymap: (commandsMod && commandsMod.defaultKeymap) || [],
history: commandsMod?.history, history: commandsMod?.history,
historyKeymap: commandsMod?.historyKeymap || [], historyKeymap: commandsMod?.historyKeymap || [],
indentWithTab: commandsMod?.indentWithTab, indentWithTab: commandsMod?.indentWithTab,
indentUnit: languageMod?.indentUnit, indentUnit: languageMod?.indentUnit,
indentOnInput: languageMod?.indentOnInput, indentOnInput: languageMod?.indentOnInput,
bracketMatching: languageMod?.bracketMatching, bracketMatching: languageMod?.bracketMatching,
foldGutter: languageMod?.foldGutter, foldGutter: languageMod?.foldGutter,
foldKeymap: languageMod?.foldKeymap, foldKeymap: languageMod?.foldKeymap,
autocompletion: autocompleteMod?.autocompletion, autocompletion: autocompleteMod?.autocompletion,
completionKeymap: autocompleteMod?.completionKeymap, completionKeymap: autocompleteMod?.completionKeymap,
closeBrackets: autocompleteMod?.closeBrackets, closeBrackets: autocompleteMod?.closeBrackets,
closeBracketsKeymap: autocompleteMod?.closeBracketsKeymap, closeBracketsKeymap: autocompleteMod?.closeBracketsKeymap,
searchKeymap: searchMod?.searchKeymap, searchKeymap: searchMod?.searchKeymap,
highlightSelectionMatches: searchMod?.highlightSelectionMatches, highlightSelectionMatches: searchMod?.highlightSelectionMatches,
lintKeymap: lintMod?.lintKeymap, lintKeymap: lintMod?.lintKeymap,
oneDark: themeOneDarkMod?.oneDark oneDark: themeOneDarkMod?.oneDark
}; };
globalAny[GLOBAL_KEY] = cache; globalAny[GLOBAL_KEY] = cache;
return cache; return cache;
} }

View File

@@ -1,131 +1,151 @@
<script lang="ts"> <script lang="ts">
import { onMount, onDestroy } from 'svelte'; import { onMount, onDestroy } from 'svelte';
import { browser } from '$app/environment'; import { browser } from '$app/environment';
import { ensureCodeMirrorModules } from './codemirror_modules'; import { ensureCodeMirrorModules } from './codemirror_modules';
export let content: string = ''; export let content: string = '';
export let placeholder: string = 'Start typing...'; export let placeholder: string = 'Start typing...';
let editor_container: HTMLDivElement; let editor_container: HTMLDivElement;
let editor_view: any; let editor_view: any;
let cm: any; // Declare cm at the top level let cm: any; // Declare cm at the top level
async function createEditor() { async function createEditor() {
if (!browser) return; if (!browser) return;
cm = await ensureCodeMirrorModules(); // Assign to the top-level cm cm = await ensureCodeMirrorModules(); // Assign to the top-level cm
if (!cm) return; if (!cm) return;
// If an existing instance exists (HMR / remount), destroy it first // If an existing instance exists (HMR / remount), destroy it first
if (editor_view && typeof editor_view.destroy === 'function') { if (editor_view && typeof editor_view.destroy === 'function') {
try { editor_view.destroy(); } catch (e) { /* ignore */ } try {
editor_view = null; editor_view.destroy();
} } catch (e) {
/* ignore */
// Build extensions defensively }
const extensions = [ editor_view = null;
cm.lineNumbers(),
cm.highlightSpecialChars(),
cm.history(),
cm.foldGutter(),
cm.drawSelection(),
cm.dropCursor(),
cm.EditorState_allowMultipleSelections.of(true),
cm.indentOnInput(),
cm.bracketMatching(),
cm.closeBrackets(),
cm.autocompletion(),
cm.rectangularSelection(),
cm.crosshairCursor(),
cm.highlightActiveLine(),
cm.highlightActiveLineGutter(),
cm.EditorView_lineWrapping,
cm.keymap.of([
...cm.defaultKeymap,
...cm.searchKeymap,
...cm.historyKeymap,
...cm.foldKeymap,
...cm.completionKeymap,
...cm.lintKeymap
]),
cm.markdown ? cm.markdown({ base: cm.markdownLanguage }) : null,
cm.EditorView && cm.EditorView.updateListener ? cm.EditorView.updateListener.of((update: any) => {
if (update.docChanged) content = update.state.doc.toString();
}) : null
].filter(Boolean);
// Create editor
editor_view = new cm.EditorView({
state: cm.EditorState.create({
doc: content ?? '',
extensions
}),
parent: editor_container
});
}
onMount(async () => {
// ensure it's created only in browser and after modules resolved
await createEditor();
});
onDestroy(() => {
if (editor_view && typeof editor_view.destroy === 'function') {
try { editor_view.destroy(); } catch (e) { /* ignore */ }
editor_view = null;
}
});
// Helper functions using the live editor_view (unchanged)
const wrapSelection = (before: string, after: string = before) => {
if (!editor_view) return;
const state = editor_view.state;
const changes = state.changeByRange((range: any) => {
const isAlreadyWrapped =
state.sliceDoc(range.from - before.length, range.from) === before &&
state.sliceDoc(range.to, range.to + after.length) === after;
if (isAlreadyWrapped) {
return {
changes: [
{ from: range.from - before.length, to: range.from, insert: '' },
{ from: range.to, to: range.to + after.length, insert: '' }
],
range: cm.EditorSelection.range(range.from - before.length, range.to - before.length)
};
} }
return { // Build extensions defensively
changes: [ const extensions = [
{ from: range.from, insert: before }, cm.lineNumbers(),
{ from: range.to, insert: after } cm.highlightSpecialChars(),
], cm.history(),
range: cm.EditorSelection.range(range.from + before.length, range.to + before.length) cm.foldGutter(),
}; cm.drawSelection(),
}); cm.dropCursor(),
editor_view.dispatch(changes); cm.EditorState_allowMultipleSelections.of(true),
editor_view.focus(); cm.indentOnInput(),
}; cm.bracketMatching(),
cm.closeBrackets(),
cm.autocompletion(),
cm.rectangularSelection(),
cm.crosshairCursor(),
cm.highlightActiveLine(),
cm.highlightActiveLineGutter(),
cm.EditorView_lineWrapping,
cm.keymap.of([
...cm.defaultKeymap,
...cm.searchKeymap,
...cm.historyKeymap,
...cm.foldKeymap,
...cm.completionKeymap,
...cm.lintKeymap
]),
cm.markdown ? cm.markdown({ base: cm.markdownLanguage }) : null,
cm.EditorView && cm.EditorView.updateListener
? cm.EditorView.updateListener.of((update: any) => {
if (update.docChanged) content = update.state.doc.toString();
})
: null
].filter(Boolean);
const insertList = () => { // Create editor
if (!editor_view) return; editor_view = new cm.EditorView({
const state = editor_view.state; state: cm.EditorState.create({
const changes = state.changeByRange((range: any) => { doc: content ?? '',
const line = state.doc.lineAt(range.from); extensions
return { }),
changes: [{ from: line.from, insert: '- ' }], parent: editor_container
range: cm.EditorSelection.range(range.from + 2, range.to + 2) });
}; }
onMount(async () => {
// ensure it's created only in browser and after modules resolved
await createEditor();
}); });
editor_view.dispatch(changes);
editor_view.focus(); onDestroy(() => {
}; if (editor_view && typeof editor_view.destroy === 'function') {
try {
editor_view.destroy();
} catch (e) {
/* ignore */
}
editor_view = null;
}
});
// Helper functions using the live editor_view (unchanged)
const wrapSelection = (before: string, after: string = before) => {
if (!editor_view) return;
const state = editor_view.state;
const changes = state.changeByRange((range: any) => {
const isAlreadyWrapped =
state.sliceDoc(range.from - before.length, range.from) === before &&
state.sliceDoc(range.to, range.to + after.length) === after;
if (isAlreadyWrapped) {
return {
changes: [
{ from: range.from - before.length, to: range.from, insert: '' },
{ from: range.to, to: range.to + after.length, insert: '' }
],
range: cm.EditorSelection.range(range.from - before.length, range.to - before.length)
};
}
return {
changes: [
{ from: range.from, insert: before },
{ from: range.to, insert: after }
],
range: cm.EditorSelection.range(range.from + before.length, range.to + before.length)
};
});
editor_view.dispatch(changes);
editor_view.focus();
};
const insertList = () => {
if (!editor_view) return;
const state = editor_view.state;
const changes = state.changeByRange((range: any) => {
const line = state.doc.lineAt(range.from);
return {
changes: [{ from: line.from, insert: '- ' }],
range: cm.EditorSelection.range(range.from + 2, range.to + 2)
};
});
editor_view.dispatch(changes);
editor_view.focus();
};
</script> </script>
<div class="codemirror-wrapper border rounded"> <div class="codemirror-wrapper border rounded">
<div class="toolbar p-1 bg-gray-100 border-b"> <div class="toolbar p-1 bg-gray-100 border-b">
<button type="button" on:click={() => wrapSelection('**')} class="px-2 py-1 rounded hover:bg-gray-200"><b>B</b></button> <button
<button type="button" on:click={() => wrapSelection('*')} class="px-2 py-1 rounded hover:bg-gray-200"><i>I</i></button> type="button"
<button type="button" on:click={insertList} class="px-2 py-1 rounded hover:bg-gray-200">List</button> on:click={() => wrapSelection('**')}
</div> class="px-2 py-1 rounded hover:bg-gray-200"><b>B</b></button
<div bind:this={editor_container} class="h-full min-h-[150px] overflow-auto"></div> >
<button
type="button"
on:click={() => wrapSelection('*')}
class="px-2 py-1 rounded hover:bg-gray-200"><i>I</i></button
>
<button type="button" on:click={insertList} class="px-2 py-1 rounded hover:bg-gray-200"
>List</button
>
</div>
<div bind:this={editor_container} class="h-full min-h-[150px] overflow-auto"></div>
</div> </div>

View File

@@ -1,21 +1,21 @@
<script lang="ts"> <script lang="ts">
import ElementCodemirrorEditor from './element_codemirror_editor.svelte'; import ElementCodemirrorEditor from './element_codemirror_editor.svelte';
import { browser } from '$app/environment'; import { browser } from '$app/environment';
export let html_text: string = ''; export let html_text: string = '';
export let placeholder: string = 'Type your text here...'; export let placeholder: string = 'Type your text here...';
export let classes: string = ''; export let classes: string = '';
</script> </script>
<div class="block w-full h-full {classes}"> <div class="block w-full h-full {classes}">
{#if browser} {#if browser}
<ElementCodemirrorEditor <ElementCodemirrorEditor
class="p-1 transition-all duration-1000" class="p-1 transition-all duration-1000"
bind:content={html_text} bind:content={html_text}
{placeholder} {placeholder}
/> />
{:else} {:else}
<!-- server / prerender placeholder to avoid SSR loading CM --> <!-- server / prerender placeholder to avoid SSR loading CM -->
<div class="p-2 text-sm text-surface-600-400">Editor (client only)</div> <div class="p-2 text-sm text-surface-600-400">Editor (client only)</div>
{/if} {/if}
</div> </div>

View File

@@ -421,11 +421,12 @@
<label for="description" class="ae_label w-full"> <label for="description" class="ae_label w-full">
<span class="legend text-sm font-semibold"> Description </span> <span class="legend text-sm font-semibold"> Description </span>
<CodeMirror_wrapper <CodeMirror_wrapper
bind:html_text={description_new_html} bind:html_text={description_new_html}
classes="preset-tonal-surface hover:preset-filled-surface-100-900" classes="preset-tonal-surface hover:preset-filled-surface-100-900"
placeholder="Your content description here..." placeholder="Your content description here..."
/> </label> />
</label>
</div> </div>
<!-- <label for="content_html">Content (HTML) <!-- <label for="content_html">Content (HTML)

View File

@@ -1,319 +1,319 @@
<script lang="ts"> <script lang="ts">
interface Props { interface Props {
log_lvl?: number; log_lvl?: number;
lq__post_obj: any; lq__post_obj: any;
// lq__post_comment_obj: any; // lq__post_comment_obj: any;
// lq__post_comment_obj_li?: any; // lq__post_comment_obj_li?: any;
}
let {
log_lvl = $bindable(1),
lq__post_obj
// lq__post_comment_obj,
// lq__post_comment_obj_li
}: Props = $props();
// *** Import Svelte specific
import { fade } from 'svelte/transition';
// *** Import other supporting libraries
// *** Import Aether specific variables and functions
import type { key_val } from '$lib/stores/ae_stores';
import { ae_util } from '$lib/ae_utils/ae_utils';
// import { core_func } from '$lib/ae_core/ae_core_functions';
import { api } from '$lib/api/api';
import {
ae_snip,
ae_loc,
ae_sess,
ae_api,
ae_trig,
slct,
slct_trigger
} from '$lib/stores/ae_stores';
import { idaa_loc, idaa_sess, idaa_slct } from '$lib/stores/ae_idaa_stores';
import { posts_func } from '$lib/ae_posts/ae_posts_functions';
import CodeMirror_wrapper from '$lib/elements/element_codemirror_editor_wrapper.svelte';
let prom_api__post_comment_obj: any = $state();
let content_new_html = $state($idaa_slct.post_comment_obj?.content ?? '');
let content_changed = $state(false);
// let notes_new_html = $state('');
// let notes_changed = $state(false);
let disable_submit_btn = $state(false);
function preventDefault<T extends Event>(fn: (event: T) => void) {
return function (event: T) {
event.preventDefault();
fn(event);
};
}
async function handle_submit_form(event: any) {
if (log_lvl > 1) {
console.log('*** handle_submit_form() ***', event.target);
} }
disable_submit_btn = true; let {
log_lvl = $bindable(1),
lq__post_obj
// lq__post_comment_obj,
// lq__post_comment_obj_li
}: Props = $props();
let form_data = new FormData(event.target); // *** Import Svelte specific
if (log_lvl > 1) { import { fade } from 'svelte/transition';
console.log(form_data);
// *** Import other supporting libraries
// *** Import Aether specific variables and functions
import type { key_val } from '$lib/stores/ae_stores';
import { ae_util } from '$lib/ae_utils/ae_utils';
// import { core_func } from '$lib/ae_core/ae_core_functions';
import { api } from '$lib/api/api';
import {
ae_snip,
ae_loc,
ae_sess,
ae_api,
ae_trig,
slct,
slct_trigger
} from '$lib/stores/ae_stores';
import { idaa_loc, idaa_sess, idaa_slct } from '$lib/stores/ae_idaa_stores';
import { posts_func } from '$lib/ae_posts/ae_posts_functions';
import CodeMirror_wrapper from '$lib/elements/element_codemirror_editor_wrapper.svelte';
let prom_api__post_comment_obj: any = $state();
let content_new_html = $state($idaa_slct.post_comment_obj?.content ?? '');
let content_changed = $state(false);
// let notes_new_html = $state('');
// let notes_changed = $state(false);
let disable_submit_btn = $state(false);
function preventDefault<T extends Event>(fn: (event: T) => void) {
return function (event: T) {
event.preventDefault();
fn(event);
};
} }
// Form Post object data incoming async function handle_submit_form(event: any) {
let post_comment_di = ae_util.extract_prefixed_form_data({ if (log_lvl > 1) {
prefix: null, console.log('*** handle_submit_form() ***', event.target);
form_data: form_data, }
trim_values: true,
bool_tf_str: true,
log_lvl: log_lvl
});
// console.log(post_comment_di);
// Form Post object data outgoing disable_submit_btn = true;
let post_comment_do: key_val = {};
if (!$idaa_slct.post_comment_id) { let form_data = new FormData(event.target);
post_comment_do['post_id_random'] = $idaa_slct.post_id; if (log_lvl > 1) {
post_comment_do['enable'] = true; console.log(form_data);
} }
// post_comment_do['title'] = post_comment_di.title; // Form Post object data incoming
let post_comment_di = ae_util.extract_prefixed_form_data({
prefix: null,
form_data: form_data,
trim_values: true,
bool_tf_str: true,
log_lvl: log_lvl
});
// console.log(post_comment_di);
// Check if the content_new_html exists and is a string // Form Post object data outgoing
if (typeof content_new_html === 'string') { let post_comment_do: key_val = {};
console.log('New content is a string');
post_comment_do['content'] = content_new_html;
} else {
console.log('New content is not a string. Do nothing.');
// post_comment_do['content'] = event_meeting_fd.content;
}
post_comment_do['anonymous'] = post_comment_di.anonymous; if (!$idaa_slct.post_comment_id) {
post_comment_do['post_id_random'] = $idaa_slct.post_id;
post_comment_do['enable'] = true;
}
post_comment_do['external_person_id'] = post_comment_di.external_person_id; // post_comment_do['title'] = post_comment_di.title;
post_comment_do['full_name'] = post_comment_di.full_name;
post_comment_do['email'] = post_comment_di.email;
post_comment_do['notify'] = post_comment_do.notify;
post_comment_do['hide'] = post_comment_di.hide; // Check if the content_new_html exists and is a string
post_comment_do['priority'] = post_comment_di.priority; if (typeof content_new_html === 'string') {
if (post_comment_di.sort) { console.log('New content is a string');
post_comment_do['sort'] = Number(post_comment_di.sort); post_comment_do['content'] = content_new_html;
} else { } else {
post_comment_do['sort'] = null; console.log('New content is not a string. Do nothing.');
} // post_comment_do['content'] = event_meeting_fd.content;
if (post_comment_di.group) { }
post_comment_do['group'] = post_comment_di.group;
} else {
post_comment_do['group'] = null;
}
// NOTE: We only want to set enable value if the input is defined. post_comment_do['anonymous'] = post_comment_di.anonymous;
if (typeof post_comment_di.enable !== 'undefined') {
post_comment_do.enable = post_comment_di.enable;
}
// NOTE: We want to always default to false if the input is not defined.
// post_comment_do.enable = post_comment_di.enable ?? false;
// // Check if the notes_new_html exists and is a string post_comment_do['external_person_id'] = post_comment_di.external_person_id;
// if (typeof $idaa_slct.post_comment_obj.notes_new_html === 'string') { post_comment_do['full_name'] = post_comment_di.full_name;
// console.log('New notes is a string'); post_comment_do['email'] = post_comment_di.email;
// post_comment_do['notes'] = $idaa_slct.post_comment_obj.notes_new_html; post_comment_do['notify'] = post_comment_do.notify;
// } else {
// console.log('New notes is not a string. Do nothing.');
// // post_comment_do['notes'] = event_meeting_fd.notes;
// }
log_lvl = 1; post_comment_do['hide'] = post_comment_di.hide;
if (log_lvl) { post_comment_do['priority'] = post_comment_di.priority;
console.log(post_comment_do); if (post_comment_di.sort) {
} post_comment_do['sort'] = Number(post_comment_di.sort);
} else {
post_comment_do['sort'] = null;
}
if (post_comment_di.group) {
post_comment_do['group'] = post_comment_di.group;
} else {
post_comment_do['group'] = null;
}
if (!$idaa_slct.post_comment_id) { // NOTE: We only want to set enable value if the input is defined.
if (typeof post_comment_di.enable !== 'undefined') {
post_comment_do.enable = post_comment_di.enable;
}
// NOTE: We want to always default to false if the input is not defined.
// post_comment_do.enable = post_comment_di.enable ?? false;
// // Check if the notes_new_html exists and is a string
// if (typeof $idaa_slct.post_comment_obj.notes_new_html === 'string') {
// console.log('New notes is a string');
// post_comment_do['notes'] = $idaa_slct.post_comment_obj.notes_new_html;
// } else {
// console.log('New notes is not a string. Do nothing.');
// // post_comment_do['notes'] = event_meeting_fd.notes;
// }
log_lvl = 1;
if (log_lvl) { if (log_lvl) {
console.log( console.log(post_comment_do);
`Current Post Comment Object List Length: ${$idaa_slct.post_comment_obj_li.length}`,
$idaa_slct.post_comment_obj_li
);
} }
prom_api__post_comment_obj = await posts_func if (!$idaa_slct.post_comment_id) {
.create_ae_obj__post_comment({ if (log_lvl) {
api_cfg: $ae_api, console.log(
post_id: $idaa_slct.post_id, `Current Post Comment Object List Length: ${$idaa_slct.post_comment_obj_li.length}`,
data_kv: post_comment_do, $idaa_slct.post_comment_obj_li
log_lvl: log_lvl );
}) }
// .then(function (post_comment_obj_create_result) {
// if (!post_comment_obj_create_result) {
// console.log('The result was null or false.');
// return false;
// }
// $idaa_slct.post_comment_id = post_comment_obj_create_result.post_comment_id_random; prom_api__post_comment_obj = await posts_func
// $idaa_slct.post_comment_obj = post_comment_obj_create_result; .create_ae_obj__post_comment({
api_cfg: $ae_api,
post_id: $idaa_slct.post_id,
data_kv: post_comment_do,
log_lvl: log_lvl
})
// .then(function (post_comment_obj_create_result) {
// if (!post_comment_obj_create_result) {
// console.log('The result was null or false.');
// return false;
// }
// return post_comment_obj_create_result; // $idaa_slct.post_comment_id = post_comment_obj_create_result.post_comment_id_random;
// }) // $idaa_slct.post_comment_obj = post_comment_obj_create_result;
.catch(function (error: any) {
console.log('Something went wrong.'); // return post_comment_obj_create_result;
console.log(error);
return false;
// }) // })
// .finally(async () => { .catch(function (error: any) {
}); console.log('Something went wrong.');
console.log(error);
return false;
// })
// .finally(async () => {
});
$idaa_slct.post_comment_id = prom_api__post_comment_obj.post_comment_id_random; $idaa_slct.post_comment_id = prom_api__post_comment_obj.post_comment_id_random;
$idaa_slct.post_comment_obj = prom_api__post_comment_obj; $idaa_slct.post_comment_obj = prom_api__post_comment_obj;
disable_submit_btn = false; disable_submit_btn = false;
$idaa_sess.bb.show__inline_edit__post_comment_id = false; $idaa_sess.bb.show__inline_edit__post_comment_id = false;
// Send notification to staff // Send notification to staff
// if (!$ae_loc.administrator_access && $ae_loc.site_cfg_json?.bb_send_staff_new_email) { // if (!$ae_loc.administrator_access && $ae_loc.site_cfg_json?.bb_send_staff_new_email) {
if ($ae_loc.site_cfg_json?.bb_send_staff_new_email) { if ($ae_loc.site_cfg_json?.bb_send_staff_new_email) {
send_staff_notification_email(); send_staff_notification_email();
} }
// Send notification to the original poster // Send notification to the original poster
if ( if (
!$ae_loc.administrator_access && !$ae_loc.administrator_access &&
$ae_loc.site_cfg_json?.bb_send_poster_email && $ae_loc.site_cfg_json?.bb_send_poster_email &&
$idaa_slct.post_obj.notify $idaa_slct.post_obj.notify
) { ) {
// if ($ae_loc.site_cfg_json?.bb_send_poster_email && $idaa_slct.post_obj.notify) { // if ($ae_loc.site_cfg_json?.bb_send_poster_email && $idaa_slct.post_obj.notify) {
send_poster_notification_email(); send_poster_notification_email();
} }
// Send a notification to any other post commenters // Send a notification to any other post commenters
if (!$ae_loc.administrator_access && $ae_loc.site_cfg_json?.bb_send_commenter_email) { if (!$ae_loc.administrator_access && $ae_loc.site_cfg_json?.bb_send_commenter_email) {
console.log( console.log(
`Sending notification email to post commenters...: ${$idaa_slct.post_comment_obj_li?.length}` `Sending notification email to post commenters...: ${$idaa_slct.post_comment_obj_li?.length}`
); );
if ($idaa_slct.post_comment_obj_li && $idaa_slct.post_comment_obj_li.length > 0) { if ($idaa_slct.post_comment_obj_li && $idaa_slct.post_comment_obj_li.length > 0) {
for (const post_comment of $idaa_slct.post_comment_obj_li) { for (const post_comment of $idaa_slct.post_comment_obj_li) {
console.log('Post Comment ID:', post_comment.post_comment_id); console.log('Post Comment ID:', post_comment.post_comment_id);
if ( if (
post_comment?.email && post_comment?.email &&
post_comment.post_comment_id !== $idaa_slct.post_comment_id && post_comment.post_comment_id !== $idaa_slct.post_comment_id &&
post_comment?.email !== $idaa_slct.post_comment_obj?.email post_comment?.email !== $idaa_slct.post_comment_obj?.email
) { ) {
console.log( console.log(
`Sending notification email to post commenter: ${post_comment.full_name}`, `Sending notification email to post commenter: ${post_comment.full_name}`,
post_comment post_comment
); );
send_poster_commenters_notification_email({ send_poster_commenters_notification_email({
post_comment_obj: post_comment post_comment_obj: post_comment
}); });
}
} }
} }
} }
return prom_api__post_comment_obj;
} else {
prom_api__post_comment_obj = posts_func
.update_ae_obj__post_comment({
api_cfg: $ae_api,
post_comment_id: $idaa_slct.post_comment_id,
data_kv: post_comment_do,
log_lvl: log_lvl
})
.then(function (post_comment_obj_update_result) {
if (!post_comment_obj_update_result) {
console.log('The result was null or false.');
return false;
}
$idaa_slct.post_comment_obj = post_comment_obj_update_result;
return post_comment_obj_update_result;
})
.catch(function (error: any) {
console.log('Something went wrong.');
console.log(error);
return false;
})
.finally(() => {
// We need to do this since the comment has changed and the idaa_slct object does automatically update (yet...???).
// $idaa_slct.post_comment_obj = $lq__post_comment_obj;
disable_submit_btn = false;
$idaa_sess.bb.show__inline_edit__post_comment_id = false;
// if (!$ae_loc.administrator_access && $ae_loc.site_cfg_json?.bb_send_staff_update_email) {
if ($ae_loc.site_cfg_json?.bb_send_staff_update_email) {
send_staff_notification_email();
}
// For now we are not going to send a notification to the poster when a post comment has been updated.
// if (!$ae_loc.administrator_access && $ae_loc.site_cfg_json?.bb_send_poster_email && $idaa_slct.post_obj.notify) {
// send_poster_notification_email();
// }
});
return prom_api__post_comment_obj;
}
}
// Updated 2024-11-15
async function handle_delete_post_comment_obj({
post_comment_id,
method = 'disable'
}: {
post_comment_id: string;
method?: string;
}) {
if (log_lvl) {
console.log('*** handle_delete_post_comment_obj() ***');
} }
return prom_api__post_comment_obj;
} else {
prom_api__post_comment_obj = posts_func prom_api__post_comment_obj = posts_func
.update_ae_obj__post_comment({ .delete_ae_obj_id__post_comment({
api_cfg: $ae_api, api_cfg: $ae_api,
post_comment_id: $idaa_slct.post_comment_id, post_comment_id: post_comment_id,
data_kv: post_comment_do, method: method,
log_lvl: log_lvl log_lvl: log_lvl
}) })
.then(function (post_comment_obj_update_result) { .then(function (post_comment_obj_delete_result) {
if (!post_comment_obj_update_result) { $idaa_sess.bb.show__inline_edit__post_comment_id = false;
console.log('The result was null or false.');
return false;
}
$idaa_slct.post_comment_obj = post_comment_obj_update_result;
return post_comment_obj_update_result;
}) })
.catch(function (error: any) { .catch(function (error: any) {
console.log('Something went wrong.'); console.log('The result was null or false when trying to delete.', error);
console.log(error);
return false;
}) })
.finally(() => { .finally(() => {
// We need to do this since the comment has changed and the idaa_slct object does automatically update (yet...???). // $idaa_sess.recovery_meetings.show__modal_edit = false;
// $idaa_slct.post_comment_obj = $lq__post_comment_obj; $idaa_slct.post_comment_id = null;
disable_submit_btn = false; $idaa_slct.post_comment_obj = null;
$idaa_sess.bb.show__inline_edit__post_comment_id = false;
// if (!$ae_loc.administrator_access && $ae_loc.site_cfg_json?.bb_send_staff_update_email) {
if ($ae_loc.site_cfg_json?.bb_send_staff_update_email) {
send_staff_notification_email();
}
// For now we are not going to send a notification to the poster when a post comment has been updated.
// if (!$ae_loc.administrator_access && $ae_loc.site_cfg_json?.bb_send_poster_email && $idaa_slct.post_obj.notify) {
// send_poster_notification_email();
// }
}); });
return prom_api__post_comment_obj; return prom_api__post_comment_obj;
} }
}
// Updated 2024-11-15 function send_staff_notification_email() {
async function handle_delete_post_comment_obj({ log_lvl = 1;
post_comment_id, if (log_lvl) {
method = 'disable' console.log(
}: { `*** send_staff_notification_email() *** Post ID: ${$idaa_slct.post_id} Post Title: ${$idaa_slct?.post_obj?.title}`
post_comment_id: string; );
method?: string; }
}) { if (log_lvl > 1) {
if (log_lvl) { console.log(`Selected Post Object:`, $idaa_slct.post_obj);
console.log('*** handle_delete_post_comment_obj() ***'); console.log(`Selected Post Comment Object:`, $idaa_slct.post_comment_obj);
}
prom_api__post_comment_obj = posts_func // console.log($lq__post_obj);
.delete_ae_obj_id__post_comment({ // console.log($lq__post_obj?.title);
api_cfg: $ae_api, // console.log($lq__post_obj?.content);
post_comment_id: post_comment_id, }
method: method,
log_lvl: log_lvl
})
.then(function (post_comment_obj_delete_result) {
$idaa_sess.bb.show__inline_edit__post_comment_id = false;
})
.catch(function (error: any) {
console.log('The result was null or false when trying to delete.', error);
})
.finally(() => {
// $idaa_sess.recovery_meetings.show__modal_edit = false;
$idaa_slct.post_comment_id = null;
$idaa_slct.post_comment_obj = null;
});
return prom_api__post_comment_obj; let link_base_url = $ae_loc.site_cfg_json.novi_bb_base_url ?? `${$ae_loc.url_origin}/idaa/bb`;
}
function send_staff_notification_email() { let subject = `IDAA BB Post Comment on: ${$idaa_slct.post_obj.title ?? '-- not set --'} (ID: ${$idaa_slct.post_id})`;
log_lvl = 1;
if (log_lvl) {
console.log(
`*** send_staff_notification_email() *** Post ID: ${$idaa_slct.post_id} Post Title: ${$idaa_slct?.post_obj?.title}`
);
}
if (log_lvl > 1) {
console.log(`Selected Post Object:`, $idaa_slct.post_obj);
console.log(`Selected Post Comment Object:`, $idaa_slct.post_comment_obj);
// console.log($lq__post_obj); let body_html = `
// console.log($lq__post_obj?.title);
// console.log($lq__post_obj?.content);
}
let link_base_url = $ae_loc.site_cfg_json.novi_bb_base_url ?? `${$ae_loc.url_origin}/idaa/bb`;
let subject = `IDAA BB Post Comment on: ${$idaa_slct.post_obj.title ?? '-- not set --'} (ID: ${$idaa_slct.post_id})`;
let body_html = `
<div>${$idaa_slct.post_obj.full_name}, <div>${$idaa_slct.post_obj.full_name},
<p>A BB post comment has been created or updated on the post named "${$idaa_slct.post_obj.title ?? '-- not set --'}".</p> <p>A BB post comment has been created or updated on the post named "${$idaa_slct.post_obj.title ?? '-- not set --'}".</p>
</div> </div>
@@ -338,29 +338,29 @@ IDAA BB Post ID: ${$idaa_slct.post_id}<br>
Copy and paste link: <a href="${link_base_url}?post_id=${$idaa_slct.post_id}">${link_base_url}?post_id=${$idaa_slct.post_id}</a></p> Copy and paste link: <a href="${link_base_url}?post_id=${$idaa_slct.post_id}">${link_base_url}?post_id=${$idaa_slct.post_id}</a></p>
</div>`; </div>`;
api.send_email({ api.send_email({
api_cfg: $ae_api, api_cfg: $ae_api,
from_email: $ae_loc.site_cfg_json?.noreply_email ?? 'noreply+idaabb@oneskyit.com', from_email: $ae_loc.site_cfg_json?.noreply_email ?? 'noreply+idaabb@oneskyit.com',
from_name: $ae_loc.site_cfg_json?.noreply_name ?? 'IDAA BB NoReply', from_name: $ae_loc.site_cfg_json?.noreply_name ?? 'IDAA BB NoReply',
to_email: $ae_loc.site_cfg_json?.admin_email ?? 'admin+bbcomment@oneskyit.com', // 'scott+idaabb@oneskyit.com', // $idaa_slct.post_comment_obj.email, to_email: $ae_loc.site_cfg_json?.admin_email ?? 'admin+bbcomment@oneskyit.com', // 'scott+idaabb@oneskyit.com', // $idaa_slct.post_comment_obj.email,
// to_email: 'scott+idaabbstaff@oneskyit.com', // to_email: 'scott+idaabbstaff@oneskyit.com',
to_name: $ae_loc.site_cfg_json?.admin_name ?? 'IDAA BB Admin', to_name: $ae_loc.site_cfg_json?.admin_name ?? 'IDAA BB Admin',
subject: subject, subject: subject,
body_html: body_html body_html: body_html
}); });
}
function send_poster_notification_email() {
log_lvl = 1;
if (log_lvl) {
console.log(`*** send_poster_notification_email() *** Post ID: ${$idaa_slct.post_id}`);
} }
let link_base_url = $ae_loc.site_cfg_json.novi_bb_base_url ?? `${$ae_loc.url_origin}/idaa/bb`; function send_poster_notification_email() {
log_lvl = 1;
if (log_lvl) {
console.log(`*** send_poster_notification_email() *** Post ID: ${$idaa_slct.post_id}`);
}
let subject = `IDAA BB Post Comment on: ${$idaa_slct.post_obj.title ?? '-- not set --'} (ID: ${$idaa_slct.post_id})`; let link_base_url = $ae_loc.site_cfg_json.novi_bb_base_url ?? `${$ae_loc.url_origin}/idaa/bb`;
let body_html = ` let subject = `IDAA BB Post Comment on: ${$idaa_slct.post_obj.title ?? '-- not set --'} (ID: ${$idaa_slct.post_id})`;
let body_html = `
<div>${$idaa_slct.post_obj.full_name ?? '-- not set --'}, <div>${$idaa_slct.post_obj.full_name ?? '-- not set --'},
<p>Your BB post named "${$idaa_slct.post_obj.title ?? '-- not set --'}" has been commented on.</p> <p>Your BB post named "${$idaa_slct.post_obj.title ?? '-- not set --'}" has been commented on.</p>
</div> </div>
@@ -373,36 +373,36 @@ IDAA BB Post ID: ${$idaa_slct.post_id}<br>
Copy and paste link: <a href="${link_base_url}?post_id=${$idaa_slct.post_id}">${link_base_url}?post_id=${$idaa_slct.post_id}</a></p> Copy and paste link: <a href="${link_base_url}?post_id=${$idaa_slct.post_id}">${link_base_url}?post_id=${$idaa_slct.post_id}</a></p>
</div>`; </div>`;
api.send_email({ api.send_email({
api_cfg: $ae_api, api_cfg: $ae_api,
from_email: $ae_loc.site_cfg_json?.noreply_email ?? 'noreply+idaabb@oneskyit.com', from_email: $ae_loc.site_cfg_json?.noreply_email ?? 'noreply+idaabb@oneskyit.com',
from_name: $ae_loc.site_cfg_json?.noreply_name ?? 'IDAA BB NoReply', from_name: $ae_loc.site_cfg_json?.noreply_name ?? 'IDAA BB NoReply',
// to_email: $ae_loc.site_cfg_json?.admin_email ?? 'admin+bbpost@oneskyit.com', // 'scott+idaabb@oneskyit.com', // to_email: $ae_loc.site_cfg_json?.admin_email ?? 'admin+bbpost@oneskyit.com', // 'scott+idaabb@oneskyit.com',
to_email: $idaa_slct.post_obj.email, to_email: $idaa_slct.post_obj.email,
// to_email: 'scott+idaabb@oneskyit.com', // to_email: 'scott+idaabb@oneskyit.com',
to_name: $idaa_slct.post_obj.full_name ?? 'IDAA BB Poster', to_name: $idaa_slct.post_obj.full_name ?? 'IDAA BB Poster',
subject: subject, subject: subject,
body_html: body_html body_html: body_html
}); });
}
function send_poster_commenters_notification_email({
post_comment_obj = $idaa_slct.post_comment_obj
}: {
post_comment_obj?: any;
} = {}) {
log_lvl = 1;
if (log_lvl) {
console.log(
`*** send_poster_commenters_notification_email() *** Post ID: ${$idaa_slct.post_id}`
);
} }
let link_base_url = $ae_loc.site_cfg_json.novi_bb_base_url ?? `${$ae_loc.url_origin}/idaa/bb`; function send_poster_commenters_notification_email({
post_comment_obj = $idaa_slct.post_comment_obj
}: {
post_comment_obj?: any;
} = {}) {
log_lvl = 1;
if (log_lvl) {
console.log(
`*** send_poster_commenters_notification_email() *** Post ID: ${$idaa_slct.post_id}`
);
}
let subject = `IDAA BB Post Comment on: ${$idaa_slct.post_obj.title ?? '-- not set --'} (ID: ${$idaa_slct.post_id})`; let link_base_url = $ae_loc.site_cfg_json.novi_bb_base_url ?? `${$ae_loc.url_origin}/idaa/bb`;
let body_html = ` let subject = `IDAA BB Post Comment on: ${$idaa_slct.post_obj.title ?? '-- not set --'} (ID: ${$idaa_slct.post_id})`;
let body_html = `
<div>${post_comment_obj.full_name ?? '-- not set --'}, <div>${post_comment_obj.full_name ?? '-- not set --'},
<p>The BB post named "${$idaa_slct.post_obj.title ?? '-- not set --'}" has been commented on.</p> <p>The BB post named "${$idaa_slct.post_obj.title ?? '-- not set --'}" has been commented on.</p>
</div> </div>
@@ -415,18 +415,18 @@ IDAA BB Post ID: ${$idaa_slct.post_id}<br>
Copy and paste link: <a href="${link_base_url}?post_id=${$idaa_slct.post_id}">${link_base_url}?post_id=${$idaa_slct.post_id}</a></p> Copy and paste link: <a href="${link_base_url}?post_id=${$idaa_slct.post_id}">${link_base_url}?post_id=${$idaa_slct.post_id}</a></p>
</div>`; </div>`;
api.send_email({ api.send_email({
api_cfg: $ae_api, api_cfg: $ae_api,
from_email: $ae_loc.site_cfg_json?.noreply_email ?? 'noreply+idaabb@oneskyit.com', from_email: $ae_loc.site_cfg_json?.noreply_email ?? 'noreply+idaabb@oneskyit.com',
from_name: $ae_loc.site_cfg_json?.noreply_name ?? 'IDAA BB NoReply', from_name: $ae_loc.site_cfg_json?.noreply_name ?? 'IDAA BB NoReply',
// to_email: $ae_loc.site_cfg_json?.admin_email ?? 'admin+bbpost@oneskyit.com', // 'scott+idaabb@oneskyit.com', // to_email: $ae_loc.site_cfg_json?.admin_email ?? 'admin+bbpost@oneskyit.com', // 'scott+idaabb@oneskyit.com',
to_email: $idaa_slct.post_obj.email, to_email: $idaa_slct.post_obj.email,
// to_email: 'scott+idaabb@oneskyit.com', // to_email: 'scott+idaabb@oneskyit.com',
to_name: $idaa_slct.post_obj.full_name ?? 'IDAA BB Post Commenter', to_name: $idaa_slct.post_obj.full_name ?? 'IDAA BB Post Commenter',
subject: subject, subject: subject,
body_html: body_html body_html: body_html
}); });
} }
</script> </script>
<section <section

View File

@@ -1,337 +1,337 @@
<script lang="ts"> <script lang="ts">
interface Props { interface Props {
log_lvl?: number; log_lvl?: number;
lq__post_obj: any; lq__post_obj: any;
obj_changed: boolean; obj_changed: boolean;
}
let { log_lvl = $bindable(0), lq__post_obj, obj_changed = $bindable(false) }: Props = $props();
// *** Import Svelte specific
// import { onDestroy, onMount } from 'svelte';
import { fade } from 'svelte/transition';
import { browser } from '$app/environment';
import { goto } from '$app/navigation';
// *** Import other supporting libraries
// *** Import Aether specific variables and functions
import type { key_val } from '$lib/stores/ae_stores';
import { ae_util } from '$lib/ae_utils/ae_utils';
import { core_func } from '$lib/ae_core/ae_core_functions';
import { api } from '$lib/api/api';
import {
ae_snip,
ae_loc,
ae_sess,
ae_api,
ae_trig,
slct,
slct_trigger
} from '$lib/stores/ae_stores';
import { idaa_loc, idaa_sess, idaa_slct } from '$lib/stores/ae_idaa_stores';
import { posts_func } from '$lib/ae_posts/ae_posts_functions';
import CodeMirror_wrapper from '$lib/elements/element_codemirror_editor_wrapper.svelte';
import Comp_hosted_files_upload from '$lib/ae_core/ae_comp__hosted_files_upload.svelte';
// let obj_changed = $state(false);
// let orig_post_obj: any = $state(null);
// let orig_post_obj: any = $state({ ...$idaa_slct.post_obj }); // Create a copy of the post object
if (!$idaa_slct.post_obj) {
$idaa_slct.post_obj = {};
}
// Create a copy of the post object
let orig_post_obj: any = { ...$idaa_slct.post_obj };
if (browser) {
// console.log(`$lq__post_obj = `, $lq__post_obj);
console.log(`$idaa_slct.post_obj = `, $idaa_slct.post_obj);
// orig_post_obj = { ...$idaa_slct.post_obj }; // Create a copy of the post object
console.log(`orig_post_obj = `, orig_post_obj);
// JSON.stringify($idaa_slct.post_obj) !== JSON.stringify(orig_post_obj)
}
if ($idaa_loc.bb.edit__post_obj) {
obj_changed = true; // This is an odd workaround to make new posts saveable.
$idaa_sess.bb.edit__post_obj = $idaa_loc.bb.edit__post_obj;
$idaa_loc.bb.edit__post_obj = false;
}
let ae_promises: key_val = $state({});
let prom_api__post_obj: any = $state();
// let prom_api__post_obj__hosted_file: any;
let content_new_html = $state($idaa_slct.post_obj?.content ?? '');
let notes_new_html = $state($idaa_slct.post_obj?.notes ?? '');
let hosted_file_id_li = $state<string[]>([]); // Array of hosted file IDs
let hosted_file_obj_li = $state<any[]>([]); // Array of hosted file objects
let upload_complete = $state(false);
let disable_submit_btn = $state(false);
function preventDefault<T extends Event>(fn: (event: T) => void) {
return function (event: T) {
event.preventDefault();
fn(event);
};
}
async function handle_submit_form(event: any) {
if (log_lvl > 1) {
console.log('*** handle_submit_form() ***', event.target);
} }
disable_submit_btn = true; let { log_lvl = $bindable(0), lq__post_obj, obj_changed = $bindable(false) }: Props = $props();
let form_data = new FormData(event.target); // *** Import Svelte specific
if (log_lvl) { // import { onDestroy, onMount } from 'svelte';
console.log(form_data); import { fade } from 'svelte/transition';
import { browser } from '$app/environment';
import { goto } from '$app/navigation';
// *** Import other supporting libraries
// *** Import Aether specific variables and functions
import type { key_val } from '$lib/stores/ae_stores';
import { ae_util } from '$lib/ae_utils/ae_utils';
import { core_func } from '$lib/ae_core/ae_core_functions';
import { api } from '$lib/api/api';
import {
ae_snip,
ae_loc,
ae_sess,
ae_api,
ae_trig,
slct,
slct_trigger
} from '$lib/stores/ae_stores';
import { idaa_loc, idaa_sess, idaa_slct } from '$lib/stores/ae_idaa_stores';
import { posts_func } from '$lib/ae_posts/ae_posts_functions';
import CodeMirror_wrapper from '$lib/elements/element_codemirror_editor_wrapper.svelte';
import Comp_hosted_files_upload from '$lib/ae_core/ae_comp__hosted_files_upload.svelte';
// let obj_changed = $state(false);
// let orig_post_obj: any = $state(null);
// let orig_post_obj: any = $state({ ...$idaa_slct.post_obj }); // Create a copy of the post object
if (!$idaa_slct.post_obj) {
$idaa_slct.post_obj = {};
}
// Create a copy of the post object
let orig_post_obj: any = { ...$idaa_slct.post_obj };
if (browser) {
// console.log(`$lq__post_obj = `, $lq__post_obj);
console.log(`$idaa_slct.post_obj = `, $idaa_slct.post_obj);
// orig_post_obj = { ...$idaa_slct.post_obj }; // Create a copy of the post object
console.log(`orig_post_obj = `, orig_post_obj);
// JSON.stringify($idaa_slct.post_obj) !== JSON.stringify(orig_post_obj)
} }
// Form Post object data incoming if ($idaa_loc.bb.edit__post_obj) {
let post_di = ae_util.extract_prefixed_form_data({ obj_changed = true; // This is an odd workaround to make new posts saveable.
prefix: null, $idaa_sess.bb.edit__post_obj = $idaa_loc.bb.edit__post_obj;
form_data: form_data, $idaa_loc.bb.edit__post_obj = false;
trim_values: true,
bool_tf_str: true,
log_lvl: log_lvl
});
// console.log(post_di);
// Form Post object data outgoing
let post_do: key_val = {};
if (!$idaa_slct.post_id) {
post_do['account_id_random'] = $ae_loc.account_id;
post_do['enable'] = true;
} }
post_do['title'] = post_di.title; let ae_promises: key_val = $state({});
let prom_api__post_obj: any = $state();
// let prom_api__post_obj__hosted_file: any;
// Check if the content_new_html exists and is a string let content_new_html = $state($idaa_slct.post_obj?.content ?? '');
if (typeof content_new_html === 'string') { let notes_new_html = $state($idaa_slct.post_obj?.notes ?? '');
console.log('New content is a string'); let hosted_file_id_li = $state<string[]>([]); // Array of hosted file IDs
post_do['content'] = content_new_html; let hosted_file_obj_li = $state<any[]>([]); // Array of hosted file objects
} else { let upload_complete = $state(false);
console.log('New content is not a string. Do nothing.'); let disable_submit_btn = $state(false);
// post_do['content'] = event_meeting_fd.content;
function preventDefault<T extends Event>(fn: (event: T) => void) {
return function (event: T) {
event.preventDefault();
fn(event);
};
} }
// Change this to a string later? Or use the group field instead? async function handle_submit_form(event: any) {
if (post_di.topic_id) { if (log_lvl > 1) {
post_do['topic_id'] = Number(post_di.topic_id); console.log('*** handle_submit_form() ***', event.target);
} else { }
post_do['topic_id'] = null;
disable_submit_btn = true;
let form_data = new FormData(event.target);
if (log_lvl) {
console.log(form_data);
}
// Form Post object data incoming
let post_di = ae_util.extract_prefixed_form_data({
prefix: null,
form_data: form_data,
trim_values: true,
bool_tf_str: true,
log_lvl: log_lvl
});
// console.log(post_di);
// Form Post object data outgoing
let post_do: key_val = {};
if (!$idaa_slct.post_id) {
post_do['account_id_random'] = $ae_loc.account_id;
post_do['enable'] = true;
}
post_do['title'] = post_di.title;
// Check if the content_new_html exists and is a string
if (typeof content_new_html === 'string') {
console.log('New content is a string');
post_do['content'] = content_new_html;
} else {
console.log('New content is not a string. Do nothing.');
// post_do['content'] = event_meeting_fd.content;
}
// Change this to a string later? Or use the group field instead?
if (post_di.topic_id) {
post_do['topic_id'] = Number(post_di.topic_id);
} else {
post_do['topic_id'] = null;
}
post_do['anonymous'] = post_di.anonymous;
post_do['external_person_id'] = post_di.external_person_id;
post_do['full_name'] = post_di.full_name;
post_do['email'] = post_di.email;
post_do['notify'] = post_di.notify;
post_do['hide'] = post_di.hide;
post_do['priority'] = post_di.priority;
if (post_di.sort) {
post_do['sort'] = Number(post_di.sort);
} else {
post_do['sort'] = null;
}
if (post_di.group) {
post_do['group'] = post_di.group;
} else {
post_do['group'] = null;
}
// NOTE: We only want to set enable value if the input is defined.
if (typeof post_di.enable !== 'undefined') {
post_do.enable = post_di.enable;
}
// NOTE: We want to always default to false if the input is not defined.
// post_do['enable'] = !!post_di.enable;
console.log(`post_di.enable = ${post_di.enable}`);
console.log(`post_do.enable = ${post_do.enable}`);
// Check if the notes_new_html exists and is a string
if (typeof notes_new_html === 'string') {
console.log('New notes is a string');
post_do['notes'] = notes_new_html;
} else {
console.log('New notes is not a string. Do nothing.');
// post_do['notes'] = event_meeting_fd.notes;
}
log_lvl = 1;
if (log_lvl) {
console.log(post_do);
}
if (!$idaa_slct.post_id) {
prom_api__post_obj = posts_func
.create_ae_obj__post({
api_cfg: $ae_api,
account_id: $ae_loc.account_id,
data_kv: post_do,
log_lvl: log_lvl
})
.then(function (post_obj_create_result) {
if (!post_obj_create_result) {
console.log('The result was null or false.');
return false;
}
if (log_lvl) {
console.log('post_obj_create_result:', post_obj_create_result);
}
$idaa_slct.post_id = post_obj_create_result.post_id_random;
$idaa_slct.post_obj = post_obj_create_result;
return post_obj_create_result;
})
.catch(function (error: any) {
console.log('Something went wrong.');
console.log(error);
return false;
})
.finally(() => {
disable_submit_btn = false;
$idaa_sess.bb.edit__post_obj = false;
// if (!$ae_loc.administrator_access && $ae_loc.site_cfg_json?.bb_send_staff_new_email) {
if ($ae_loc.site_cfg_json?.bb_send_staff_new_email) {
send_staff_notification_email();
}
});
return prom_api__post_obj;
} else {
prom_api__post_obj = posts_func
.update_ae_obj__post({
api_cfg: $ae_api,
post_id: $idaa_slct.post_id,
data_kv: post_do,
log_lvl: log_lvl
})
.then(function (post_obj_update_result) {
if (!post_obj_update_result) {
console.log('The result was null or false.');
return false;
}
$idaa_slct.post_obj = post_obj_update_result;
return post_obj_update_result;
})
.catch(function (error: any) {
console.log('Something went wrong.');
console.log(error);
return false;
})
.finally(() => {
// We need to do this since the post has changed and the idaa_slct object does automatically update (yet...???).
// $idaa_slct.post_obj = $lq__post_obj;
disable_submit_btn = false;
$idaa_sess.bb.edit__post_obj = false;
// if (!$ae_loc.administrator_access && $ae_loc.site_cfg_json?.bb_send_staff_update_email) {
if ($ae_loc.site_cfg_json?.bb_send_staff_update_email) {
send_staff_notification_email();
}
});
return prom_api__post_obj;
}
} }
post_do['anonymous'] = post_di.anonymous; // Updated 2024-11-15
async function handle_delete_post_obj({
post_id,
method = 'disable'
}: {
post_id: string;
method?: string;
}) {
if (log_lvl) {
console.log('*** handle_delete_post_obj() ***');
}
post_do['external_person_id'] = post_di.external_person_id;
post_do['full_name'] = post_di.full_name;
post_do['email'] = post_di.email;
post_do['notify'] = post_di.notify;
post_do['hide'] = post_di.hide;
post_do['priority'] = post_di.priority;
if (post_di.sort) {
post_do['sort'] = Number(post_di.sort);
} else {
post_do['sort'] = null;
}
if (post_di.group) {
post_do['group'] = post_di.group;
} else {
post_do['group'] = null;
}
// NOTE: We only want to set enable value if the input is defined.
if (typeof post_di.enable !== 'undefined') {
post_do.enable = post_di.enable;
}
// NOTE: We want to always default to false if the input is not defined.
// post_do['enable'] = !!post_di.enable;
console.log(`post_di.enable = ${post_di.enable}`);
console.log(`post_do.enable = ${post_do.enable}`);
// Check if the notes_new_html exists and is a string
if (typeof notes_new_html === 'string') {
console.log('New notes is a string');
post_do['notes'] = notes_new_html;
} else {
console.log('New notes is not a string. Do nothing.');
// post_do['notes'] = event_meeting_fd.notes;
}
log_lvl = 1;
if (log_lvl) {
console.log(post_do);
}
if (!$idaa_slct.post_id) {
prom_api__post_obj = posts_func prom_api__post_obj = posts_func
.create_ae_obj__post({ .delete_ae_obj_id__post({
api_cfg: $ae_api, api_cfg: $ae_api,
account_id: $ae_loc.account_id, post_id: post_id,
data_kv: post_do, method: method,
log_lvl: log_lvl log_lvl: log_lvl
}) })
.then(function (post_obj_create_result) { .then(function (post_obj_delete_result) {
if (!post_obj_create_result) { // $idaa_sess.bb.show__modal_view__post_id = false;
console.log('The result was null or false.'); $idaa_sess.bb.edit__post_obj = false;
return false; // $idaa_sess.bb.show__inline_edit__post_comment_id = false;
}
if (log_lvl) {
console.log('post_obj_create_result:', post_obj_create_result);
}
$idaa_slct.post_id = post_obj_create_result.post_id_random;
$idaa_slct.post_obj = post_obj_create_result;
return post_obj_create_result;
}) })
.catch(function (error: any) { .catch(function (error: any) {
console.log('Something went wrong.'); console.log('The result was null or false when trying to delete.', error);
console.log(error);
return false;
}) })
.finally(() => { .finally(() => {
disable_submit_btn = false; // $idaa_sess.recovery_meetings.show__modal_edit = false;
$idaa_sess.bb.edit__post_obj = false; $idaa_slct.post_id = null;
$idaa_slct.post_obj = null;
// if (!$ae_loc.administrator_access && $ae_loc.site_cfg_json?.bb_send_staff_new_email) { $idaa_slct.post_comment_id = null;
if ($ae_loc.site_cfg_json?.bb_send_staff_new_email) { $idaa_slct.post_comment_obj = null;
send_staff_notification_email(); goto('/idaa/bb'); // Redirect to the BB page
}
}); });
return prom_api__post_obj; return prom_api__post_obj;
} else { }
async function handle_hosted_files_uploaded(
hosted_file_id_li: string[],
hosted_file_obj_li: any[]
) {
console.log(`*** handle_hosted_files_uploaded() *** ${hosted_file_id_li}`);
// NOTE: No longer directly updating the $idaa_slct.post_obj.hosted_file_obj_li. This will be updated when the PATCH API for Post update finishes.
// We need to add the record to the $idaa_slct.post_obj.hosted_file_obj_li and then update the post_obj.linked_li_json with the new value.
// let new_linked_li_json = [...$idaa_slct.post_obj.linked_li_json ?? {}]; // Initialize with existing linked_li_json or an empty array
let new_linked_li_json = $idaa_slct.post_obj.linked_li_json ?? []; // Initialize with existing linked_li_json or an empty array
if (!$idaa_slct.post_obj.linked_li_json) {
// $idaa_slct.post_obj.linked_li_json = hosted_file_obj_li;
new_linked_li_json = hosted_file_obj_li;
} else {
$idaa_slct.post_obj.linked_li_json.push(...hosted_file_obj_li);
new_linked_li_json = [...new_linked_li_json];
// new_linked_li_json.push(...hosted_file_obj_li);
// new_linked_li_json = [...new_linked_li_json];
}
prom_api__post_obj = posts_func prom_api__post_obj = posts_func
.update_ae_obj__post({ .update_ae_obj__post({
api_cfg: $ae_api, api_cfg: $ae_api,
post_id: $idaa_slct.post_id, post_id: $idaa_slct.post_id,
data_kv: post_do, data_kv: {
// linked_li_json: JSON.stringify($idaa_slct.post_obj.linked_li_json),
linked_li_json: JSON.stringify(new_linked_li_json)
},
log_lvl: log_lvl log_lvl: log_lvl
}) })
.then(function (post_obj_update_result) { .then(function (post_obj_update_result) {
if (!post_obj_update_result) { // $idaa_slct.post_obj = $lq__post_obj;
console.log('The result was null or false.');
return false;
}
$idaa_slct.post_obj = post_obj_update_result;
return post_obj_update_result;
}) })
.catch(function (error: any) { .catch(function (error: any) {
console.log('Something went wrong.'); console.log('Something went wrong.');
console.log(error); console.log(error);
return false; return false;
})
.finally(() => {
// We need to do this since the post has changed and the idaa_slct object does automatically update (yet...???).
// $idaa_slct.post_obj = $lq__post_obj;
disable_submit_btn = false;
$idaa_sess.bb.edit__post_obj = false;
// if (!$ae_loc.administrator_access && $ae_loc.site_cfg_json?.bb_send_staff_update_email) {
if ($ae_loc.site_cfg_json?.bb_send_staff_update_email) {
send_staff_notification_email();
}
}); });
return prom_api__post_obj;
}
}
// Updated 2024-11-15
async function handle_delete_post_obj({
post_id,
method = 'disable'
}: {
post_id: string;
method?: string;
}) {
if (log_lvl) {
console.log('*** handle_delete_post_obj() ***');
} }
prom_api__post_obj = posts_func function send_staff_notification_email() {
.delete_ae_obj_id__post({ if (log_lvl) {
api_cfg: $ae_api, console.log(`*** send_staff_notification_email() *** Post ID: ${$idaa_slct.post_id}`);
post_id: post_id, }
method: method,
log_lvl: log_lvl
})
.then(function (post_obj_delete_result) {
// $idaa_sess.bb.show__modal_view__post_id = false;
$idaa_sess.bb.edit__post_obj = false;
// $idaa_sess.bb.show__inline_edit__post_comment_id = false;
})
.catch(function (error: any) {
console.log('The result was null or false when trying to delete.', error);
})
.finally(() => {
// $idaa_sess.recovery_meetings.show__modal_edit = false;
$idaa_slct.post_id = null;
$idaa_slct.post_obj = null;
$idaa_slct.post_comment_id = null;
$idaa_slct.post_comment_obj = null;
goto('/idaa/bb'); // Redirect to the BB page
});
return prom_api__post_obj; let link_base_url = $ae_loc.site_cfg_json.novi_bb_base_url ?? `${$ae_loc.url_origin}/idaa/bb`;
}
async function handle_hosted_files_uploaded( let subject = `IDAA BB Post: ${$idaa_slct.post_obj.title} (ID: ${$idaa_slct.post_id})`;
hosted_file_id_li: string[],
hosted_file_obj_li: any[]
) {
console.log(`*** handle_hosted_files_uploaded() *** ${hosted_file_id_li}`);
// NOTE: No longer directly updating the $idaa_slct.post_obj.hosted_file_obj_li. This will be updated when the PATCH API for Post update finishes. let body_html = `
// We need to add the record to the $idaa_slct.post_obj.hosted_file_obj_li and then update the post_obj.linked_li_json with the new value.
// let new_linked_li_json = [...$idaa_slct.post_obj.linked_li_json ?? {}]; // Initialize with existing linked_li_json or an empty array
let new_linked_li_json = $idaa_slct.post_obj.linked_li_json ?? []; // Initialize with existing linked_li_json or an empty array
if (!$idaa_slct.post_obj.linked_li_json) {
// $idaa_slct.post_obj.linked_li_json = hosted_file_obj_li;
new_linked_li_json = hosted_file_obj_li;
} else {
$idaa_slct.post_obj.linked_li_json.push(...hosted_file_obj_li);
new_linked_li_json = [...new_linked_li_json];
// new_linked_li_json.push(...hosted_file_obj_li);
// new_linked_li_json = [...new_linked_li_json];
}
prom_api__post_obj = posts_func
.update_ae_obj__post({
api_cfg: $ae_api,
post_id: $idaa_slct.post_id,
data_kv: {
// linked_li_json: JSON.stringify($idaa_slct.post_obj.linked_li_json),
linked_li_json: JSON.stringify(new_linked_li_json)
},
log_lvl: log_lvl
})
.then(function (post_obj_update_result) {
// $idaa_slct.post_obj = $lq__post_obj;
})
.catch(function (error: any) {
console.log('Something went wrong.');
console.log(error);
return false;
});
}
function send_staff_notification_email() {
if (log_lvl) {
console.log(`*** send_staff_notification_email() *** Post ID: ${$idaa_slct.post_id}`);
}
let link_base_url = $ae_loc.site_cfg_json.novi_bb_base_url ?? `${$ae_loc.url_origin}/idaa/bb`;
let subject = `IDAA BB Post: ${$idaa_slct.post_obj.title} (ID: ${$idaa_slct.post_id})`;
let body_html = `
<div>${$idaa_slct.post_obj.full_name ?? '-- not set --'}, <div>${$idaa_slct.post_obj.full_name ?? '-- not set --'},
<p>A BB post has been created or updated named "${$idaa_slct.post_obj.title}".</p> <p>A BB post has been created or updated named "${$idaa_slct.post_obj.title}".</p>
</div> </div>
@@ -350,50 +350,50 @@ IDAA BB Post ID: ${$idaa_slct.post_id}<br>
Copy and paste link: <a href="${link_base_url}?post_id=${$idaa_slct.post_id}">${link_base_url}?post_id=${$idaa_slct.post_id}</a></p> Copy and paste link: <a href="${link_base_url}?post_id=${$idaa_slct.post_id}">${link_base_url}?post_id=${$idaa_slct.post_id}</a></p>
</div>`; </div>`;
api.send_email({ api.send_email({
api_cfg: $ae_api, api_cfg: $ae_api,
from_email: $ae_loc.site_cfg_json?.noreply_email ?? 'noreply+idaabb@oneskyit.com', from_email: $ae_loc.site_cfg_json?.noreply_email ?? 'noreply+idaabb@oneskyit.com',
// from_email: 'noreply+idaabb@oneskyit.com', // from_email: 'noreply+idaabb@oneskyit.com',
from_name: $ae_loc.site_cfg_json?.noreply_name ?? 'IDAA BB NoReply', from_name: $ae_loc.site_cfg_json?.noreply_name ?? 'IDAA BB NoReply',
to_email: $ae_loc.site_cfg_json?.admin_email ?? 'admin+bbpost@oneskyit.com', to_email: $ae_loc.site_cfg_json?.admin_email ?? 'admin+bbpost@oneskyit.com',
// to_email: 'test+idaabb@oneskyit.com', // 'scott+idaabb@oneskyit.com' // to_email: 'test+idaabb@oneskyit.com', // 'scott+idaabb@oneskyit.com'
to_name: $ae_loc.site_cfg_json?.admin_name ?? 'IDAA BB Admin', to_name: $ae_loc.site_cfg_json?.admin_name ?? 'IDAA BB Admin',
subject: subject, subject: subject,
body_html: body_html body_html: body_html
});
}
$effect(() => {
if (orig_post_obj === null || orig_post_obj === undefined || orig_post_obj === 'undefined') {
obj_changed = false;
} else if (
!obj_changed &&
orig_post_obj?.id &&
(JSON.stringify($idaa_slct.post_obj) !== JSON.stringify(orig_post_obj) ||
content_new_html !== (orig_post_obj.content ?? '') ||
notes_new_html !== (orig_post_obj.notes ?? ''))
) {
// console.log('Post object has changed from original.', $inspect(orig_post_obj));
console.log('Post object has changed from original.', orig_post_obj);
console.log('Post object has changed.', $idaa_slct.post_obj);
obj_changed = true;
} else if (
obj_changed &&
orig_post_obj?.id &&
JSON.stringify($idaa_slct.post_obj) === JSON.stringify(orig_post_obj) &&
content_new_html === (orig_post_obj.content ?? '') &&
notes_new_html === (orig_post_obj.notes ?? '')
) {
obj_changed = false;
}
}); });
}
$effect(() => { $effect(() => {
if (orig_post_obj === null || orig_post_obj === undefined || orig_post_obj === 'undefined') { if (upload_complete && hosted_file_id_li?.length && hosted_file_obj_li?.length) {
obj_changed = false; handle_hosted_files_uploaded(hosted_file_id_li, hosted_file_obj_li);
} else if ( upload_complete = false; // Reset the upload complete flag
!obj_changed && }
orig_post_obj?.id && });
(JSON.stringify($idaa_slct.post_obj) !== JSON.stringify(orig_post_obj) ||
content_new_html !== (orig_post_obj.content ?? '') ||
notes_new_html !== (orig_post_obj.notes ?? ''))
) {
// console.log('Post object has changed from original.', $inspect(orig_post_obj));
console.log('Post object has changed from original.', orig_post_obj);
console.log('Post object has changed.', $idaa_slct.post_obj);
obj_changed = true;
} else if (
obj_changed &&
orig_post_obj?.id &&
JSON.stringify($idaa_slct.post_obj) === JSON.stringify(orig_post_obj) &&
content_new_html === (orig_post_obj.content ?? '') &&
notes_new_html === (orig_post_obj.notes ?? '')
) {
obj_changed = false;
}
});
$effect(() => {
if (upload_complete && hosted_file_id_li?.length && hosted_file_obj_li?.length) {
handle_hosted_files_uploaded(hosted_file_id_li, hosted_file_obj_li);
upload_complete = false; // Reset the upload complete flag
}
});
</script> </script>
<section <section