This commit is contained in:
Florian THIERRY
2024-09-21 21:34:16 +02:00
parent 208b935ffa
commit f8d73c9ed0
12 changed files with 110 additions and 76 deletions

View File

@@ -91,7 +91,7 @@
"extractLicenses": false, "extractLicenses": false,
"sourceMap": true, "sourceMap": true,
"localize": ["fr"], "localize": ["fr"],
"i18nMissingTranslation": "warning" "i18nMissingTranslation": "error"
} }
}, },
"defaultConfiguration": "" "defaultConfiguration": ""

View File

@@ -2,12 +2,12 @@
<mat-icon>close</mat-icon> <mat-icon>close</mat-icon>
</button> </button>
<header> <header>
<h1>Add a code block</h1> <h1 i18n>Add a code block</h1>
</header> </header>
<form [formGroup]="formGroup" (submit)="closeAndValidate()" ngNativeValidate> <form [formGroup]="formGroup" (submit)="closeAndValidate()" ngNativeValidate>
<div class="form-content"> <div class="form-content">
<mat-form-field> <mat-form-field>
<mat-label>Programming language</mat-label> <mat-label i18n>Programming language</mat-label>
<mat-select #programmingLanguageSelect formControlName="programmingLanguage"> <mat-select #programmingLanguageSelect formControlName="programmingLanguage">
@for(programmingLanguage of programmingLanguages; track programmingLanguage) { @for(programmingLanguage of programmingLanguages; track programmingLanguage) {
<mat-option [value]="programmingLanguage.code"> <mat-option [value]="programmingLanguage.code">
@@ -17,15 +17,15 @@
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
<mat-form-field> <mat-form-field>
<mat-label>Code block</mat-label> <mat-label i18n>Code block</mat-label>
<textarea matInput formControlName="codeBlock"></textarea> <textarea matInput formControlName="codeBlock"></textarea>
</mat-form-field> </mat-form-field>
</div> </div>
<div class="actions"> <div class="actions">
<button type="submit"> <button type="submit" i18n>
Validate Validate
</button> </button>
<button type="button" (click)="closeDialog()" class="secondary"> <button type="button" (click)="closeDialog()" class="secondary" i18n>
Cancel Cancel
</button> </button>
</div> </div>

View File

@@ -2,27 +2,27 @@
<mat-icon>close</mat-icon> <mat-icon>close</mat-icon>
</button> </button>
<header> <header>
<h1>Select an illustration:</h1> <h1 i18n>Select an illustration</h1>
</header> </header>
<div class="picture-container"> <div class="picture-container">
@if (isLoading) { @if (isLoading) {
<h2>Pictures loading...</h2> <h2 i18n>Pictures loading...</h2>
<mat-spinner></mat-spinner> <mat-spinner></mat-spinner>
} @else { } @else {
@if (pictures.length) { @if (pictures.length) {
@for(picture of pictures; track picture) { @for(picture of pictures; track picture) {
<img src="/api/pictures/{{picture.id}}" (click)="selectPicture(picture)" matTooltip="Choose this illustration"/> <img src="/api/pictures/{{picture.id}}" (click)="selectPicture(picture)" matTooltip="Choose this illustration" i18n-matTooltip/>
} }
} @else { } @else {
<h2>There is no any picture.</h2> <h2 i18n>There is no any picture.</h2>
} }
} }
</div> </div>
<footer> <footer>
<button type="button" class="secondary" matRipple (click)="closeDialog()"> <button type="button" class="secondary" matRipple (click)="closeDialog()" i18n>
Cancel Cancel
</button> </button>
<button type="button" (click)="fileUpload.click()" matRipple> <button type="button" (click)="fileUpload.click()" matRipple i18n>
<mat-icon>upload_file</mat-icon> <mat-icon>upload_file</mat-icon>
Add new picture Add new picture
</button> </button>

View File

@@ -34,9 +34,9 @@ export class PictureSelectionDialog implements OnInit {
if (error.status === 401) { if (error.status === 401) {
this.dialogRef.close(); this.dialogRef.close();
} else { } else {
const errorMessage = 'An error occured while loading pictures.'; const errorMessage = $localize`An error occured while loading pictures.`;
console.error(errorMessage, error); console.error(errorMessage, error);
this.snackBar.open(errorMessage, 'Close', { duration: 5000 }); this.snackBar.open(errorMessage, $localize`Close`, { duration: 5000 });
} }
}) })
.finally(() => { .finally(() => {
@@ -61,9 +61,9 @@ export class PictureSelectionDialog implements OnInit {
this.dialogRef.close(pictureId); this.dialogRef.close(pictureId);
}) })
.catch(error => { .catch(error => {
const errorMessage = 'A technical error occured while uploading your picture.'; const errorMessage = $localize`A technical error occured while uploading your picture.`;
console.error(errorMessage, error); console.error(errorMessage, error);
this.snackBar.open(errorMessage, 'Close', { duration: 5000 }); this.snackBar.open(errorMessage, $localize`Close`, { duration: 5000 });
}); });
} }
} }

View File

@@ -16,9 +16,9 @@ export class PictureSelectionDialogService {
this.dialogRef.close(pictureId); this.dialogRef.close(pictureId);
}) })
.catch(error => { .catch(error => {
const errorMessage = 'An error occured while uploading a picture...'; const errorMessage = $localize`An error occured while uploading a picture...`;
console.error(errorMessage, error); console.error(errorMessage, error);
this.snackBar.open(errorMessage, 'Close', { duration: 5000 }); this.snackBar.open(errorMessage, $localize`Close`, { duration: 5000 });
}); });
} }
} }

View File

@@ -9,15 +9,15 @@
<div class="first-part"> <div class="first-part">
<div> <div>
<mat-form-field> <mat-form-field>
<mat-label>Title</mat-label> <mat-label i18n>Title</mat-label>
<input matInput type="text" formControlName="title" /> <input matInput type="text" formControlName="title" />
</mat-form-field> </mat-form-field>
<mat-form-field> <mat-form-field>
<mat-label>Description</mat-label> <mat-label i18n>Description</mat-label>
<input matInput type="text" formControlName="description" /> <input matInput type="text" formControlName="description" />
</mat-form-field> </mat-form-field>
<mat-form-field> <mat-form-field>
<mat-label>Category</mat-label> <mat-label i18n>Category</mat-label>
<mat-select formControlName="categoryId"> <mat-select formControlName="categoryId">
@for (category of categories$ | async; track category) { @for (category of categories$ | async; track category) {
<mat-option [value]="category.id"> <mat-option [value]="category.id">
@@ -31,35 +31,36 @@
<div class="picture-container"> <div class="picture-container">
<img [src]="publication.illustrationId.length ? '/api/pictures/' + publication.illustrationId : '/assets/images/default-picture.png'" <img [src]="publication.illustrationId.length ? '/api/pictures/' + publication.illustrationId : '/assets/images/default-picture.png'"
(click)="displayPictureSectionDialog()" (click)="displayPictureSectionDialog()"
matTooltip="Click to change illustration"/> matTooltip="Click to change illustration"
i18n-matTooltip/>
</div> </div>
</div> </div>
<div class="actions"> <div class="actions">
<button type="button" matTooltip="Click to insert a title 1 section" (click)="insertTitle(1)"> <button type="button" matTooltip="Click to insert a title 1 section" (click)="insertTitle(1)" i18n-matTooltip>
H1 H1
</button> </button>
<button type="button" matTooltip="Click to insert a title 2 section" (click)="insertTitle(2)"> <button type="button" matTooltip="Click to insert a title 2 section" (click)="insertTitle(2)" i18n-matTooltip>
H2 H2
</button> </button>
<button type="button" matTooltip="Click to insert a title 1 section" (click)="insertTitle(3)"> <button type="button" matTooltip="Click to insert a title 1 section" (click)="insertTitle(3)" i18n-matTooltip>
H3 H3
</button> </button>
<button type="button" matTooltip="Click to insert a picture" (click)="selectAPicture()"> <button type="button" matTooltip="Click to insert a picture" (click)="selectAPicture()" i18n-matTooltip>
<mat-icon>image</mat-icon> <mat-icon>image</mat-icon>
</button> </button>
<button type="button" matTooltip="Click to insert a link" (click)="insertLink()"> <button type="button" matTooltip="Click to insert a link" (click)="insertLink()" i18n-matTooltip>
<mat-icon>link</mat-icon> <mat-icon>link</mat-icon>
</button> </button>
<button type="button" matTooltip="Click to insert a code block" (click)="displayCodeBlockDialog()"> <button type="button" matTooltip="Click to insert a code block" (click)="displayCodeBlockDialog()" i18n-matTooltip>
<mat-icon>code</mat-icon> <mat-icon>code</mat-icon>
</button> </button>
<button type="button" disabled matTooltip="Click to display editor help"> <button type="button" disabled matTooltip="Click to display editor help" i18n-matTooltip>
<mat-icon>help</mat-icon> <mat-icon>help</mat-icon>
</button> </button>
</div> </div>
<mat-form-field class="example-form-field"> <mat-form-field>
<mat-label>Content</mat-label> <mat-label i18n>Content</mat-label>
<textarea <textarea
#textArea #textArea
matInput matInput
@@ -76,7 +77,7 @@
<div class="preview"> <div class="preview">
@if ((isPreviewing$ | async) === true) { @if ((isPreviewing$ | async) === true) {
<div class="preview-loading"> <div class="preview-loading">
<h2>Preview is loading...</h2> <h2 i18n>Preview is loading...</h2>
<mat-spinner></mat-spinner> <mat-spinner></mat-spinner>
</div> </div>
} @else { } @else {
@@ -91,8 +92,8 @@
</mat-tab> </mat-tab>
</mat-tab-group> </mat-tab-group>
<footer> <footer>
<app-submit-button label="Save" [requestPending]="!!(isSaving$ | async)"></app-submit-button> <app-submit-button label="Save" [requestPending]="!!(isSaving$ | async)" i18n-label></app-submit-button>
<button type="button" class="secondary" (click)="goPreviousLocation()"> <button type="button" class="secondary" (click)="goPreviousLocation()" i18n>
Cancel Cancel
</button> </button>
</footer> </footer>

View File

@@ -178,8 +178,6 @@ export class PublicationEditionComponent implements OnChanges, OnDestroy {
const positionStart = textarea.selectionStart; const positionStart = textarea.selectionStart;
const positionEnd = textarea.selectionEnd; const positionEnd = textarea.selectionEnd;
const selectedCharacterCount = positionEnd - positionStart;
console.log(`cursor position updated: [${positionStart}, ${positionEnd}] (${selectedCharacterCount})`);
this.publicationEditionService.editCursorPosition(positionStart, positionEnd); this.publicationEditionService.editCursorPosition(positionStart, positionEnd);
} }
} }

View File

@@ -101,7 +101,7 @@ export class PublicationEditionService implements OnDestroy {
this.activatedRoute.paramMap.subscribe(params => { this.activatedRoute.paramMap.subscribe(params => {
const publicationId = params.get('publicationId'); const publicationId = params.get('publicationId');
if (publicationId == undefined) { if (publicationId == undefined) {
this.snackBar.open('A technical error occurred while loading publication data.', 'Close', {duration: 5000}); this.snackBar.open($localize`A technical error occurred while loading publication data.`, $localize`Close`, { duration: 5000 });
this.location.back(); this.location.back();
} else { } else {
this.publicationRestService.getById(publicationId) this.publicationRestService.getById(publicationId)
@@ -111,8 +111,8 @@ export class PublicationEditionService implements OnDestroy {
this.stateSubject.next(state); this.stateSubject.next(state);
}) })
.catch(error => { .catch(error => {
const errorMessage = 'A technical error occurred while loading publication data.'; const errorMessage = $localize`A technical error occurred while loading publication data.`;
this.snackBar.open(errorMessage, 'Close', {duration: 5000}); this.snackBar.open(errorMessage, $localize`Close`, {duration: 5000});
console.error(errorMessage, error) console.error(errorMessage, error)
}) })
.finally(() => this.isLoadingSubject.next(false)); .finally(() => this.isLoadingSubject.next(false));

View File

@@ -4,11 +4,11 @@
<img src="assets/images/codiki.png" alt="logo"/> <img src="assets/images/codiki.png" alt="logo"/>
Codiki Codiki
</a> </a>
<button type="button" (click)="close()" matTooltip="Close the menu"> <button type="button" (click)="close()" matTooltip="Close the menu" i18n-matTooltip>
<mat-icon>close</mat-icon> <mat-icon>close</mat-icon>
</button> </button>
</h1> </h1>
<h2>Catégories</h2> <h2 i18n>Categories</h2>
<app-categories-menu (categoryClicked)="close()"></app-categories-menu> <app-categories-menu (categoryClicked)="close()"></app-categories-menu>
</div> </div>
<div class="overlay {{ isOpenned ? 'displayed' : ''}}" (click)="close()"></div> <div class="overlay {{ isOpenned ? 'displayed' : ''}}" (click)="close()"></div>

View File

@@ -1,9 +1,8 @@
import { Injectable, OnDestroy, inject } from '@angular/core'; import { Injectable, inject } from '@angular/core';
import { CategoryService } from '../../core/service/category.service';
import { BehaviorSubject, Observable, Subscription, map } from 'rxjs';
import { Category } from '../../core/rest-services/category/model/category';
import { CategoryRestService } from '../../core/rest-services/category/category.rest-service';
import { MatSnackBar } from '@angular/material/snack-bar'; import { MatSnackBar } from '@angular/material/snack-bar';
import { BehaviorSubject, Observable } from 'rxjs';
import { CategoryRestService } from '../../core/rest-services/category/category.rest-service';
import { Category } from '../../core/rest-services/category/model/category';
export interface DisplayableCategory { export interface DisplayableCategory {
id: string; id: string;
@@ -20,31 +19,13 @@ export interface DisplayableSubCategory {
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class SideMenuService implements OnDestroy { export class SideMenuService {
private categoryRestService = inject(CategoryRestService); private categoryRestService = inject(CategoryRestService);
private snackBar = inject(MatSnackBar); private snackBar = inject(MatSnackBar);
private categoriesSubject = new BehaviorSubject<DisplayableCategory[]>([]); private categoriesSubject = new BehaviorSubject<DisplayableCategory[]>([]);
private isLoadingSubject = new BehaviorSubject<boolean>(false); private isLoadingSubject = new BehaviorSubject<boolean>(false);
private isLoadedSubject = new BehaviorSubject<boolean>(false); private isLoadedSubject = new BehaviorSubject<boolean>(false);
constructor() {
// this.categoriesSubscription = this.categoryService.categories$
// .pipe(
// map(categories =>
// categories
// .filter(category => category.subCategories?.length)
// .map(category =>
// this.mapToDisplayableCategory(category)
// )
// )
// )
// .subscribe(categories => this.categoriesSubject.next(categories));
}
ngOnDestroy(): void {
// this.categoriesSubscription?.unsubscribe();
}
private mapToDisplayableCategory(category: Category): DisplayableCategory { private mapToDisplayableCategory(category: Category): DisplayableCategory {
return { return {
id: category.id, id: category.id,
@@ -89,9 +70,9 @@ export class SideMenuService implements OnDestroy {
this.categoriesSubject.next(displayableCategories); this.categoriesSubject.next(displayableCategories);
}) })
.catch(error => { .catch(error => {
const errorMessage = "An error occured while loading categories."; const errorMessage = $localize`An error occured while loading categories.`;
console.error(errorMessage, error); console.error(errorMessage, error);
this.snackBar.open(errorMessage, 'Close', { duration: 5000 }); this.snackBar.open(errorMessage, $localize`Close`, { duration: 5000 });
}) })
.finally(() => { .finally(() => {
this.isLoadingSubject.next(false); this.isLoadingSubject.next(false);

View File

@@ -10,12 +10,40 @@
"3394094310583807145": "{$START_TAG_MAT_ICON}description{$CLOSE_TAG_MAT_ICON} Mes publications", "3394094310583807145": "{$START_TAG_MAT_ICON}description{$CLOSE_TAG_MAT_ICON} Mes publications",
"5690703874094076840": "{$START_TAG_MAT_ICON}logout{$CLOSE_TAG_MAT_ICON} Déconnexion", "5690703874094076840": "{$START_TAG_MAT_ICON}logout{$CLOSE_TAG_MAT_ICON} Déconnexion",
"2454050363478003966": "Connexion", "2454050363478003966": "Connexion",
"6379828571327118783": "Ajouter un bloc de code",
"933522671092765466": "Langage de programmation",
"5953425146193292178": "Bloc de code",
"7975252153657972743": "Valider",
"2330577642930707695": "Annuler",
"162921950259491830": "Sélectionnez une illustation",
"1678880547384144969": "Chargement des images...",
"4111988153902305972": "Choisir cette illustation",
"4491342806775118195": "Il n'y a aucune image.",
"5036131155743433968": "{$START_TAG_MAT_ICON}upload_file{$CLOSE_TAG_MAT_ICON} Ajouter une nouvelle image",
"6852365376059142995": "Une erreur est survenue lors du chargements de vos images.",
"7819314041543176992": "Fermer",
"6198966268398913224": "Une erreur technique est survenue lors de l'ajout de votre image.",
"5701618810648052610": "Titre",
"4902817035128594900": "Description",
"1806667489382256324": "Categorie",
"4954740313142081867": "Cliquer pour changer l'illustation",
"382530603854484923": "Cliquez pour ajouter une section titre de niveau 1",
"7918008528690631661": "Cliquez pour ajouter une section titre de niveau 2",
"327371240590280003": "Cliquez pour ajouter une image",
"2615926469669796978": "Cliquez pour ajouter un lien",
"4689637499823680515": "Cliquez pour ajouter un bloc de code",
"1065684538660053227": "Cliquez pour afficher l'aide",
"6205355627445317276": "Contenu",
"1775659119052622417": "La prévisualisation charge...",
"3768927257183755959": "Enregistrer",
"4580042433737768435": "Une erreur technique est survenue lors du chargement de la publication à modifier.",
"2578598149846191609": "Publication postée par {$INTERPOLATION}", "2578598149846191609": "Publication postée par {$INTERPOLATION}",
"6514394873612421064": "Rechercher quelque chose...", "6514394873612421064": "Rechercher quelque chose...",
"3450287383703155559": "Vous n'êtes pas connecté. Veuillez vous connecter avant de réessayer.", "9122763438636464100": "Fermer le menu",
"7819314041543176992": "Fermer", "1902100407096396858": "Catégories",
"5455465794443528807": "You n'êtes pas connecté. Veuillez vous connecter avant de réessayer votre opération.",
"6940115735259407353": "Une erreur est survenue lors du chargement des catégories.", "6940115735259407353": "Une erreur est survenue lors du chargement des catégories.",
"3450287383703155559": "Vous n'êtes pas connecté. Veuillez vous connecter avant de réessayer.",
"5455465794443528807": "You n'êtes pas connecté. Veuillez vous connecter avant de réessayer votre opération.",
"4011987306265136481": "Déconnexion...", "4011987306265136481": "Déconnexion...",
"4869473828758837325": "Dernières publications", "4869473828758837325": "Dernières publications",
"5148998676057880041": "Chargement des publications...", "5148998676057880041": "Chargement des publications...",
@@ -38,7 +66,6 @@
"5585500423922995936": "Chargement de la publication à modifier...", "5585500423922995936": "Chargement de la publication à modifier...",
"1487849090405054079": "Modification de la publication {$INTERPOLATION}", "1487849090405054079": "Modification de la publication {$INTERPOLATION}",
"570282468314450588": "La publication n'a pas pu être chargée...", "570282468314450588": "La publication n'a pas pu être chargée...",
"4580042433737768435": "Une erreur technique est survenue lors du chargement de la publication à modifier.",
"1766298802296530620": "Publication modifiée avec succès !", "1766298802296530620": "Publication modifiée avec succès !",
"5690532907092398845": "Une erreur est survenue lors de l'enregistrement des modifications de la publication.", "5690532907092398845": "Une erreur est survenue lors de l'enregistrement des modifications de la publication.",
"9035578711395348230": "Chargement du contenu de la publication...", "9035578711395348230": "Chargement du contenu de la publication...",
@@ -50,7 +77,7 @@
"886526241743571962": "Recherche des publications...", "886526241743571962": "Recherche des publications...",
"3467080651873197381": "Il n'y a aucun résultat.", "3467080651873197381": "Il n'y a aucun résultat.",
"8212807341111457015": "Une erreur est survenue lors de la recherche des publications..", "8212807341111457015": "Une erreur est survenue lors de la recherche des publications..",
"2101902914887471883": "Inscription", "2101902914887471883": "Créer un compte",
"963610942522043725": "Pseudo {$START_TAG_SPAN}*{$CLOSE_TAG_SPAN}", "963610942522043725": "Pseudo {$START_TAG_SPAN}*{$CLOSE_TAG_SPAN}",
"5090593460426139718": "Confirmation du mot de passe {$START_TAG_SPAN}*{$CLOSE_TAG_SPAN}", "5090593460426139718": "Confirmation du mot de passe {$START_TAG_SPAN}*{$CLOSE_TAG_SPAN}",
"3461230574295546047": "J'ai déjà un compte", "3461230574295546047": "J'ai déjà un compte",

View File

@@ -10,12 +10,40 @@
"3394094310583807145": "{$START_TAG_MAT_ICON}description{$CLOSE_TAG_MAT_ICON} My publications ", "3394094310583807145": "{$START_TAG_MAT_ICON}description{$CLOSE_TAG_MAT_ICON} My publications ",
"5690703874094076840": "{$START_TAG_MAT_ICON}logout{$CLOSE_TAG_MAT_ICON} Disconnect ", "5690703874094076840": "{$START_TAG_MAT_ICON}logout{$CLOSE_TAG_MAT_ICON} Disconnect ",
"2454050363478003966": "Login", "2454050363478003966": "Login",
"6379828571327118783": "Add a code block",
"933522671092765466": "Programming language",
"5953425146193292178": "Code block",
"7975252153657972743": " Validate ",
"2330577642930707695": " Cancel ",
"162921950259491830": "Select an illustration",
"1678880547384144969": "Pictures loading...",
"4111988153902305972": "Choose this illustration",
"4491342806775118195": "There is no any picture.",
"5036131155743433968": "{$START_TAG_MAT_ICON}upload_file{$CLOSE_TAG_MAT_ICON} Add new picture ",
"6852365376059142995": "An error occured while loading pictures.",
"7819314041543176992": "Close",
"6198966268398913224": "A technical error occured while uploading your picture.",
"5701618810648052610": "Title",
"4902817035128594900": "Description",
"1806667489382256324": "Category",
"4954740313142081867": "Click to change illustration",
"382530603854484923": "Click to insert a title 1 section",
"7918008528690631661": "Click to insert a title 2 section",
"327371240590280003": "Click to insert a picture",
"2615926469669796978": "Click to insert a link",
"4689637499823680515": "Click to insert a code block",
"1065684538660053227": "Click to display editor help",
"6205355627445317276": "Content",
"1775659119052622417": "Preview is loading...",
"3768927257183755959": "Save",
"4580042433737768435": "A technical error occurred while loading publication data.",
"2578598149846191609": "Publication posted by {$INTERPOLATION}", "2578598149846191609": "Publication posted by {$INTERPOLATION}",
"6514394873612421064": "Search something...", "6514394873612421064": "Search something...",
"3450287383703155559": "You are unauthenticated. Please, log-in first.", "9122763438636464100": "Close the menu",
"7819314041543176992": "Close", "1902100407096396858": "Categories",
"5455465794443528807": "You are unauthenticated. Please, re-authenticate before retrying your action.",
"6940115735259407353": "An error occured while loading categories.", "6940115735259407353": "An error occured while loading categories.",
"3450287383703155559": "You are unauthenticated. Please, log-in first.",
"5455465794443528807": "You are unauthenticated. Please, re-authenticate before retrying your action.",
"4011987306265136481": "Disconnection...", "4011987306265136481": "Disconnection...",
"4869473828758837325": "Last publications", "4869473828758837325": "Last publications",
"5148998676057880041": "Publications loading...", "5148998676057880041": "Publications loading...",
@@ -38,7 +66,6 @@
"5585500423922995936": "Loading publication to edit...", "5585500423922995936": "Loading publication to edit...",
"1487849090405054079": "Update publication {$INTERPOLATION}", "1487849090405054079": "Update publication {$INTERPOLATION}",
"570282468314450588": "Publication failed to load...", "570282468314450588": "Publication failed to load...",
"4580042433737768435": "A technical error occurred while loading publication data.",
"1766298802296530620": "Publication updated succesfully!", "1766298802296530620": "Publication updated succesfully!",
"5690532907092398845": "An error occured while saving publication modifications.", "5690532907092398845": "An error occured while saving publication modifications.",
"9035578711395348230": "Publication content loading...", "9035578711395348230": "Publication content loading...",