Skip to content

Commit

Permalink
feat: Implement create article from existing note page - EXO-73041 - M…
Browse files Browse the repository at this point in the history
…eeds-io/MIPs#161 (#310)

Implement create article from exiting note page
  • Loading branch information
hakermi authored Nov 18, 2024
1 parent 8f577ea commit 8e7bed3
Show file tree
Hide file tree
Showing 11 changed files with 148 additions and 60 deletions.
2 changes: 2 additions & 0 deletions content-service/src/main/java/io/meeds/news/model/News.java
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,6 @@ public class News {
private String latestVersionId;

private NotePageProperties properties;

private boolean fromDraft;
}
12 changes: 7 additions & 5 deletions content-service/src/main/java/io/meeds/news/rest/NewsRest.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package io.meeds.news.rest;

import static io.meeds.news.utils.NewsUtils.NewsObjectType.ARTICLE;
import static io.meeds.news.utils.NewsUtils.NewsObjectType.EXISTING_PAGE;

import java.util.ArrayList;
import java.util.HashMap;
Expand Down Expand Up @@ -634,12 +635,13 @@ public ResponseEntity<News> scheduleNews(@Parameter(description = "News object t
}
org.exoplatform.services.security.Identity currentIdentity = ConversationState.getCurrent().getIdentity();
try {
News news = newsService.getNewsById(scheduledNews.getId(), currentIdentity, false, newsObjectType);
if (news == null) {
return ResponseEntity.notFound().build();
if (!newsObjectType.equalsIgnoreCase(EXISTING_PAGE.name())) {
News news = newsService.getNewsById(scheduledNews.getId(), currentIdentity, false, newsObjectType);
if (news == null) {
return ResponseEntity.notFound().build();
}
}
news = newsService.scheduleNews(scheduledNews, currentIdentity, newsObjectType);
return ResponseEntity.ok(news);
return ResponseEntity.ok(newsService.scheduleNews(scheduledNews, currentIdentity, newsObjectType));
} catch (IllegalAccessException e) {
LOG.warn("User '{}' is not autorized to schedule news", currentIdentity.getUserId(), e);
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ News scheduleNews(News news,

/**
* Checks if the user can schedule publishinga News
*
*
* @param space target space
* @param currentIdentity current user identity
* @param article target article
Expand All @@ -303,7 +303,7 @@ News scheduleNews(News news,

/**
* Shares a news item into a dedicated space
*
*
* @param news {@link News} to share
* @param space {@link Space} to share with, the news
* @param userIdentity {@link Identity} of user making the modification
Expand All @@ -325,6 +325,16 @@ News createDraftArticleForNewPage(News draftArticle,
String draftArticleCreator,
long creationDate) throws Exception;

/**
* Create an article from exiting page
*
* @param article article object
* @param creator article creator
* @return {@link News}
* @throws Exception
*/
News createArticleFromExistingPage(News article, String creator) throws Exception;

/**
* @param newsArticle {@link News} news article to be created
* @param newsArticleCreator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import static io.meeds.news.utils.NewsUtils.NewsObjectType.LATEST_DRAFT;
import static io.meeds.news.utils.NewsUtils.NewsUpdateType.CONTENT_AND_TITLE;

import java.text.ParseException;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
Expand Down Expand Up @@ -240,6 +239,8 @@ public News createNews(News news, Identity currentIdentity) throws Exception {
public News postNews(News news, String poster) throws Exception {
if (news.getPublicationState().equals(STAGED) || news.getSchedulePostDate() != null) {
news = postScheduledArticle(news);
} else if (!news.isFromDraft() && noteService.getNoteById(news.getId()) != null) {
news = createArticleFromExistingPage(news, poster);
} else {
news = createNewsArticlePage(news, poster);
}
Expand Down Expand Up @@ -750,6 +751,8 @@ public News scheduleNews(News news, Identity currentIdentity, String newsObjectT
// it will be posted and published by the news schedule job or the edit
// scheduling.
news = createNewsArticlePage(news, currentIdentity.getUserId());
} else if (newsObjectType.equalsIgnoreCase(NewsObjectType.EXISTING_PAGE.name())) {
news = createArticleFromExistingPage(news, currentIdentity.getUserId());
} else if (newsObjectType.equalsIgnoreCase(ARTICLE.name())) {
updateArticle(news, currentIdentity, NewsUtils.NewsUpdateType.SCHEDULE.name().toLowerCase());
}
Expand Down Expand Up @@ -957,6 +960,21 @@ public News createDraftArticleForNewPage(News draftArticle,
return null;
}

/**
* {@inheritDoc}
*/
@Override
public News createArticleFromExistingPage(News article, String creator) throws Exception {
Page articlePage = noteService.getNoteById(article.getId());
Space space = spaceService.getSpaceById(article.getSpaceId());
if (articlePage != null && space != null) {
PageVersion pageVersion = noteService.getPublishedVersionByPageIdAndLang(Long.parseLong(articlePage.getId()), null);
article.setIllustrationURL(NewsUtils.buildIllustrationUrl(articlePage.getProperties(), articlePage.getLang()));
buildNewArticleProperties(article, articlePage, creator, space.getId(), pageVersion.getId());
}
return article;
}

/**
* {@inheritDoc}
*/
Expand Down Expand Up @@ -1010,44 +1028,8 @@ public News createNewsArticlePage(News newsArticle, String newsArticleCreator) t
newsArticle.setProperties(newsArticlePage.getProperties());
newsArticle.setLatestVersionId(pageVersion.getId());
newsArticle.setIllustrationURL(NewsUtils.buildIllustrationUrl(newsArticlePage.getProperties(), newsArticle.getLang()));

NewsPageVersionObject newsArticleVersionMetaDataObject = new NewsPageVersionObject(NEWS_METADATA_PAGE_VERSION_OBJECT_TYPE,
pageVersion.getId(),
null,
Long.parseLong(space.getId()));
String newsArticleMetadataItemCreatorIdentityId = identityManager.getOrCreateUserIdentity(newsArticleCreator).getId();
Map<String, String> newsArticleVersionMetadataItemProperties = new HashMap<>();

// create the page version metadata item
metadataService.createMetadataItem(newsArticleVersionMetaDataObject,
NEWS_METADATA_KEY,
newsArticleVersionMetadataItemProperties,
Long.parseLong(newsArticleMetadataItemCreatorIdentityId),
false);

// create metadata item page
NewsPageObject newsPageObject = new NewsPageObject(NEWS_METADATA_PAGE_OBJECT_TYPE,
newsArticlePage.getId(),
null,
Long.parseLong(space.getId()));
Map<String, String> newsPageProperties = new HashMap<>();
if (StringUtils.isNotEmpty(newsArticle.getAudience())) {
newsPageProperties.put(NEWS_AUDIENCE, newsArticle.getAudience());
}

setScheduleProperties(newsArticle, newsPageProperties);

if (StringUtils.isNotEmpty(newsArticle.getPublicationState())) {
newsPageProperties.put(NEWS_PUBLICATION_STATE, newsArticle.getPublicationState());
}
newsPageProperties.put(NEWS_ACTIVITY_POSTED, String.valueOf(newsArticle.isActivityPosted()));
newsPageProperties.put(PUBLISHED, String.valueOf(newsArticle.isPublished()));
newsPageProperties.put(NEWS_DELETED, String.valueOf(newsArticlePage.isDeleted()));
metadataService.createMetadataItem(newsPageObject,
NEWS_METADATA_KEY,
newsPageProperties,
Long.parseLong(newsArticleMetadataItemCreatorIdentityId),
false);
buildNewArticleProperties(newsArticle, newsArticlePage, newsArticleCreator, space.getId(), pageVersion.getId());
// delete the draft
deleteDraftArticle(draftNewsId, poster.getUserId());
return newsArticle;
Expand Down Expand Up @@ -1178,6 +1160,48 @@ public void deleteDraftArticle(String draftArticleId, String draftArticleCreator
public List<String> getArticleLanguages(String articleId, boolean withDrafts) throws WikiException {
return noteService.getPageAvailableTranslationLanguages(Long.parseLong(articleId), withDrafts);
}

private void buildNewArticleProperties(News article,
Page articlePage,
String creator,
String spaceId,
String versionId) throws Exception {
NewsPageVersionObject articleVersionMetaDataObject = new NewsPageVersionObject(NEWS_METADATA_PAGE_VERSION_OBJECT_TYPE,
versionId,
null,
Long.parseLong(spaceId));
String creatorIdentityId = identityManager.getOrCreateUserIdentity(creator).getId();
Map<String, String> newsArticleVersionMetadataItemProperties = new HashMap<>();
// create the page version metadata item
metadataService.createMetadataItem(articleVersionMetaDataObject,
NEWS_METADATA_KEY,
newsArticleVersionMetadataItemProperties,
Long.parseLong(creatorIdentityId),
false);

// create metadata item page
NewsPageObject newsPageObject = new NewsPageObject(NEWS_METADATA_PAGE_OBJECT_TYPE,
articlePage.getId(),
null,
Long.parseLong(spaceId));
Map<String, String> newsPageProperties = new HashMap<>();
if (StringUtils.isNotEmpty(article.getAudience())) {
newsPageProperties.put(NEWS_AUDIENCE, article.getAudience());
}
setScheduleProperties(article, newsPageProperties);

if (StringUtils.isNotEmpty(article.getPublicationState())) {
newsPageProperties.put(NEWS_PUBLICATION_STATE, article.getPublicationState());
}
newsPageProperties.put(NEWS_ACTIVITY_POSTED, String.valueOf(article.isActivityPosted()));
newsPageProperties.put(PUBLISHED, String.valueOf(article.isPublished()));
newsPageProperties.put(NEWS_DELETED, String.valueOf(articlePage.isDeleted()));
metadataService.createMetadataItem(newsPageObject,
NEWS_METADATA_KEY,
newsPageProperties,
Long.parseLong(creatorIdentityId),
false);
}

private News updateDraftArticleForNewPage(News draftArticle, String draftArticleUpdater, Space space) throws WikiException,
IllegalAccessException {
Expand Down Expand Up @@ -1897,7 +1921,7 @@ private News buildArticle(String newsId, String lang, boolean fetchOriginal) thr
articlePage.getId(),
null,
Long.parseLong(space.getId()));
MetadataItem metadataItem = metadataService.getMetadataItemsByMetadataAndObject(NEWS_METADATA_KEY, newsPageObject).get(0);
MetadataItem metadataItem = metadataService.getMetadataItemsByMetadataAndObject(NEWS_METADATA_KEY, newsPageObject).getFirst();
buildArticleProperties(news, currentUsername, metadataItem);
news.setDeleted(articlePage.isDeleted());
news.setPublicationDate(articlePage.getCreatedDate());
Expand All @@ -1914,14 +1938,6 @@ private News buildArticle(String newsId, String lang, boolean fetchOriginal) thr
news.setIllustrationURL(NewsUtils.buildIllustrationUrl(news.getProperties(), pageVersion.getLang()));

}

NewsPageVersionObject newsPageVersionObject = new NewsPageVersionObject(NEWS_METADATA_PAGE_VERSION_OBJECT_TYPE,
pageVersion.getId(),
null,
Long.parseLong(space.getId()));
List<MetadataItem> newsPageVersionMetadataItems =
metadataService.getMetadataItemsByMetadataAndObject(NEWS_METADATA_KEY,
newsPageVersionObject);
return news;
}
}
Expand Down Expand Up @@ -2031,7 +2047,7 @@ private void processPageContent(Page page, News news) throws Exception {
}

private String parseAndNormalizeScheduleDate(String date, String timeZoneId) {
if(StringUtils.isBlank(date)) {
if(StringUtils.isBlank(date) || date.equals("0")) {
return null;
}
ZoneId userTimeZone = StringUtils.isBlank(timeZoneId) ? ZoneId.of("UTC") : ZoneId.of(timeZoneId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public class NewsUtils {
public static final String UPDATE_CONTENT_PERMISSIONS = "content.update.permissions";

public enum NewsObjectType {
DRAFT, LATEST_DRAFT, ARTICLE;
DRAFT, LATEST_DRAFT, ARTICLE, EXISTING_PAGE
}

public enum NewsUpdateType {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -540,9 +540,25 @@ public void testPostNews() throws Exception {
verify(noteService, times(1)).getPublishedVersionByPageIdAndLang(1L, null);
verify(metadataService, atLeast(1)).createMetadataItem(any(MetadataObject.class),
any(MetadataKey.class),
any(Map.class),
anyMap(),
anyLong(),
anyBoolean());
Page note = new Page();
note.setId("1");
note.setTitle(newsArticle.getTitle());
note.setContent(newsArticle.getBody());
note.setParentPageId(rootPage.getId());
note.setAuthor(newsArticle.getAuthor());
when(noteService.getNoteById(anyString())).thenReturn(note);
clearInvocations(noteService, metadataService);
newsService.createNews(newsArticle, identity);
verify(noteService, times(0)).createNote(wiki, rootPage.getName(), newsArticlePage, identity);
verify(noteService, times(1)).getPublishedVersionByPageIdAndLang(1L, null);
verify(metadataService, atLeast(1)).createMetadataItem(any(MetadataObject.class),
any(MetadataKey.class),
anyMap(),
anyLong(),
anyBoolean());
}

@Test
Expand Down
28 changes: 28 additions & 0 deletions content-webapp/src/main/webapp/WEB-INF/gatein-resources.xml
Original file line number Diff line number Diff line change
Expand Up @@ -587,4 +587,32 @@
<as>$</as>
</depends>
</module>

<module>
<name>NotePublishExtensions</name>
<script>
<minify>false</minify>
<path>/js/notePublishExtensions.bundle.js</path>
</script>
<depends>
<module>vue</module>
</depends>
<depends>
<module>vuetify</module>
</depends>
<depends>
<module>eXoVueI18n</module>
</depends>
<depends>
<module>jquery</module>
<as>$</as>
</depends>
<depends>
<module>extensionRegistry</module>
</depends>
<depends>
<module>commonVueComponents</module>
</depends>
</module>

</gatein-resources>
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,7 @@ export default {
audience: this.article.audience,
draftPage: this.article.publicationState === 'draft',
scheduleUnpublishDate: this.article.scheduleUnpublishDate,
fromDraft: true,
properties: this.article?.properties
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import * as newsTargetingService from '../../services/newsTargetingService.js';
import * as newsService from '../../services/newsServices.js';


if (!Vue.prototype.$newsTargetingService) {
window.Object.defineProperty(Vue.prototype, '$newsTargetingService', {
value: newsTargetingService,
});
}
if (!Vue.prototype.$newsService) {
window.Object.defineProperty(Vue.prototype, '$newsService', {
value: newsService,
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ export function getNewsById(id, editMode, type, lang) {
} else if ( resp.status === 401) {
return resp.status;
}
}).catch((error) => {
return error;
});
}

Expand Down
3 changes: 2 additions & 1 deletion content-webapp/webpack.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ let config = {
newsAnalyticsExtensions: './src/main/webapp/vue-app/news-extensions/analytics-extensions/main.js',
newsNotificationExtensions: './src/main/webapp/vue-app/news-extensions/notification-extensions/main.js',
engagementCenterExtensions: './src/main/webapp/vue-app/engagementCenterExtensions/extensions.js',
contentTranslationMenu: './src/main/webapp/vue-app/newsTranslationMenu/main.js'
contentTranslationMenu: './src/main/webapp/vue-app/newsTranslationMenu/main.js',
notePublishExtensions: './src/main/webapp/vue-app/news-extensions/note-publish-extensions/main.js',
},
output: {
filename: 'js/[name].bundle.js',
Expand Down

0 comments on commit 8e7bed3

Please sign in to comment.