Skip to content

Commit

Permalink
feat: Implement refer/derefer article page - EXO-73046_EXO-73047 - Me…
Browse files Browse the repository at this point in the history
…eds-io/MIPs#161 (#330)

Implement refer/derefer article page in/from notes
  • Loading branch information
hakermi committed Dec 11, 2024
1 parent b2b15fe commit c5d7906
Show file tree
Hide file tree
Showing 20 changed files with 210 additions and 17 deletions.
6 changes: 6 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 @@ -146,5 +146,11 @@ public class News {
private boolean fromDraft;

private boolean fromExternalPage;

private boolean canRefer;

private boolean isReferred;

private long deReferPageId;

}
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ public ResponseEntity<News> updateNews(@PathVariable("id")
news.setScheduleUnpublishDate(updatedNews.getScheduleUnpublishDate());
news.setProperties(updatedNews.getProperties());
news.setLang(updatedNews.getLang());
news.setReferred(updatedNews.isReferred());
news = newsService.updateNews(news, currentIdentity.getUserId(), post, updatedNews.isPublished(), newsObjectType, newsUpdateType);

return ResponseEntity.ok(news);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,13 @@
import static io.meeds.news.utils.NewsUtils.NewsObjectType.ARTICLE;
import static io.meeds.news.utils.NewsUtils.NewsObjectType.LATEST_DRAFT;
import static io.meeds.news.utils.NewsUtils.NewsUpdateType.CONTENT_AND_TITLE;
import static io.meeds.news.utils.NewsUtils.NewsUpdateType.PAGE_REFERENCE;

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.*;
import java.util.regex.Matcher;
import java.util.stream.Stream;

Expand Down Expand Up @@ -168,6 +161,10 @@ public class NewsServiceImpl implements NewsService {
public static final String NEWS_METADATA_LATEST_DRAFT_OBJECT_TYPE = "newsLatestDraftPage";

public static final String EXTERNAL_PAGE = "externalPage";

public static final String PAGE_REFERRED = "pageReferred";

public static final String DE_REFER_PAGE_ID = "deReferPageId";

public static final String ARTICLE_CONTENT = "content";

Expand Down Expand Up @@ -292,6 +289,8 @@ public News updateNews(News news,
} else if (ARTICLE.name().equalsIgnoreCase(newsObjectType) && CONTENT_AND_TITLE.name().equalsIgnoreCase(newsUpdateType)
&& StringUtils.isNotEmpty(news.getLang())) {
return addNewArticleVersionWithLang(news, updaterIdentity, space);
} else if (ARTICLE.name().equalsIgnoreCase(newsObjectType) && PAGE_REFERENCE.name().equalsIgnoreCase(newsUpdateType)) {
return updateArticle(news, updaterIdentity, newsUpdateType);
}
if (publish != news.isPublished() && news.isCanPublish()) {
news.setPublished(publish);
Expand Down Expand Up @@ -513,6 +512,7 @@ public News getNewsByIdAndLang(String newsId,
news.setCanEdit(canEditNews(news, currentIdentity.getUserId()));
news.setCanDelete(canDeleteNews(currentIdentity, news));
news.setCanPublish(NewsUtils.canPublishNews(news.getSpaceId(), currentIdentity));
news.setCanRefer(NewsUtils.canReferToNote(news.getSpaceId(), news, currentIdentity));
Space space = spaceService.getSpaceById(news.getSpaceId());
if (space != null) {
news.setCanSchedule(canScheduleNews(space, currentIdentity, news));
Expand Down Expand Up @@ -579,6 +579,7 @@ public List<News> getNews(NewsFilter filter, Identity currentIdentity) throws Ex
news.setCanEdit(canEditNews(news, currentIdentity.getUserId()));
news.setCanDelete(canDeleteNews(currentIdentity, news));
news.setCanPublish(NewsUtils.canPublishNews(news.getSpaceId(), currentIdentity));
news.setCanRefer(NewsUtils.canReferToNote(news.getSpaceId(), news, currentIdentity));
Space space = spaceService.getSpaceById(news.getSpaceId());
if (space != null) {
news.setCanSchedule(canScheduleNews(space, currentIdentity, news));
Expand Down Expand Up @@ -1232,6 +1233,16 @@ private void buildNewArticleProperties(News article,
false);
}

private void referOrDeReferArticlePage(News article, Page articlePage, Map<String, String> properties) {
if (article.isReferred()) {
properties.put(PAGE_REFERRED, Boolean.TRUE.toString());
properties.put(DE_REFER_PAGE_ID, articlePage.getParentPageId());
} else {
properties.remove(PAGE_REFERRED);
properties.remove(DE_REFER_PAGE_ID);
}
}

private News updateDraftArticleForNewPage(News draftArticle, String draftArticleUpdater, Space space) throws WikiException,
IllegalAccessException {
DraftPage draftArticlePage = noteService.getDraftNoteById(draftArticle.getId(), draftArticleUpdater);
Expand Down Expand Up @@ -1362,6 +1373,12 @@ private void buildArticleProperties(News article, String currentUsername, Metada
if (properties.containsKey(EXTERNAL_PAGE) && StringUtils.isNotEmpty(properties.get(EXTERNAL_PAGE))) {
article.setFromExternalPage(Boolean.parseBoolean(properties.get(EXTERNAL_PAGE)));
}
if (properties.containsKey(PAGE_REFERRED) && StringUtils.isNotEmpty(properties.get(PAGE_REFERRED))) {
article.setReferred(Boolean.parseBoolean(properties.get(PAGE_REFERRED)));
}
if (properties.containsKey(DE_REFER_PAGE_ID) && StringUtils.isNotEmpty(properties.get(DE_REFER_PAGE_ID))) {
article.setDeReferPageId(Long.parseLong(properties.get(DE_REFER_PAGE_ID)));
}
if (properties.containsKey(NEWS_VIEWS) && StringUtils.isNotEmpty(properties.get(NEWS_VIEWS))) {
article.setViewsCount(Long.parseLong(properties.get(NEWS_VIEWS)));
}
Expand Down Expand Up @@ -1881,6 +1898,7 @@ private News updateArticle(News news, Identity updater, String newsUpdateType) t
if (StringUtils.isNotEmpty(news.getPublicationState())) {
newsPageProperties.put(NEWS_PUBLICATION_STATE, news.getPublicationState());
}
referOrDeReferArticlePage(news, existingPage, newsPageProperties);
newsPageProperties.put(NEWS_ACTIVITY_POSTED, String.valueOf(news.isActivityPosted()));
existingPageMetadataItem.setProperties(newsPageProperties);
Date updateDate = Calendar.getInstance().getTime();
Expand Down
25 changes: 23 additions & 2 deletions content-service/src/main/java/io/meeds/news/utils/NewsUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,14 @@ public class NewsUtils {

public static final String UPDATE_CONTENT_PERMISSIONS = "content.update.permissions";

private static SpaceService spaceService;

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

public enum NewsUpdateType {
CONTENT_AND_TITLE, SCHEDULE, POSTING_AND_PUBLISHING
CONTENT_AND_TITLE, SCHEDULE, POSTING_AND_PUBLISHING, PAGE_REFERENCE
}

public static void broadcastEvent(String eventName, Object source, Object data) {
Expand Down Expand Up @@ -283,10 +285,29 @@ public static String buildIllustrationUrl(NotePageProperties properties, String
return illustrationUrl.toString();
}

public static boolean canReferToNote(String spaceId, News article, org.exoplatform.services.security.Identity currentIdentity) {
Space space = getSpaceService().getSpaceById(spaceId);
if (space == null || currentIdentity == null) {
return false;
}
if (article.isFromExternalPage()) {
return false;
}
return getSpaceService().canRedactOnSpace(space, currentIdentity)
|| getSpaceService().canPublishOnSpace(space, currentIdentity.getUserId());
}

private static SpaceService getSpaceService() {
if (spaceService == null) {
spaceService = CommonsUtils.getService(SpaceService.class);
}
return spaceService;
}

private static List<Space> getMySpaces(org.exoplatform.services.security.Identity userIdentity) throws Exception {
SpaceService spaceService = CommonsUtils.getService(SpaceService.class);
ListAccess<Space> memberSpacesListAccess = spaceService.getMemberSpaces(userIdentity.getUserId());
return Arrays.asList(memberSpacesListAccess.load(0, memberSpacesListAccess.getSize()));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -281,3 +281,10 @@ content.alert.success.label.translation.deleted=Translation successfully deleted
article.automatic.translation.label=Automatic translation
article.label.translation.originalVersion=Original version
article.label.chooseLanguage=Choose a language

content.article.refer.to.note=Refer in the Notes
content.article.refer.label=Refer
content.article.deRefer.label=Derefer the note
content.article.referred.success=Article successfully referred
content.article.referred.error=Error while referring article
content.article.deReferred.success=Note dereferred successfully
Original file line number Diff line number Diff line change
Expand Up @@ -281,3 +281,10 @@ content.alert.success.label.translation.deleted=La traduction a été supprimée
article.automatic.translation.label=Traduction automatique
article.label.translation.originalVersion=Version originale
article.label.chooseLanguage=Choisir une langue

content.article.refer.to.note=R\u00E9f\u00E9rencer dans les notes
content.article.refer.label=R\u00E9f\u00E9rencer
content.article.deRefer.label=D\u00E9r\u00E9f\u00E9rencer la note
content.article.referred.success=Article r\u00E9f\u00E9renc\u00E9 avec succ\u00E8s
content.article.referred.error=Erreur lors de la r\u00E9f\u00E9rence de l'article
content.article.deReferred.success=Note d\u00E9r\u00E9f\u00E9renc\u00E9e avec succ\u00E8s
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when;

import io.meeds.news.model.News;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
Expand Down Expand Up @@ -53,6 +55,11 @@ public class NewsUtilsTest {
@Mock
private Identity adminAclIdentity;

@Before
public void setUp() {
COMMONS_UTILS.when(() -> CommonsUtils.getService(SpaceService.class)).thenReturn(spaceService);
}

@AfterClass
public static void afterRunBare() throws Exception { // NOSONAR
COMMONS_UTILS.close();
Expand All @@ -64,7 +71,6 @@ public void testCanPublishNews() {
when(space.getId()).thenReturn("2");

assertFalse(NewsUtils.canPublishNews(null, null));
COMMONS_UTILS.when(() -> CommonsUtils.getService(SpaceService.class)).thenReturn(spaceService);
assertFalse(NewsUtils.canPublishNews(space.getId(), null));
assertFalse(NewsUtils.canPublishNews(space.getId(), userAclIdentity));

Expand Down Expand Up @@ -93,4 +99,23 @@ public void testCanPublishNews() {
assertTrue(NewsUtils.canPublishNews(space.getId(), userAclIdentity));
}

@Test
public void testCanReferArticleToNote() {
News article = new News();
when(userAclIdentity.getUserId()).thenReturn("user");
when(spaceService.getSpaceById("2")).thenReturn(null, space);
assertFalse(NewsUtils.canReferToNote("2", article, null));
assertFalse(NewsUtils.canReferToNote("2", article, null));

article.setFromExternalPage(true);
assertFalse(NewsUtils.canReferToNote("2", article, userAclIdentity));
article.setFromExternalPage(false);
when(spaceService.canRedactOnSpace(space, userAclIdentity)).thenReturn(false, true, false, true);
when(spaceService.canPublishOnSpace(space, "user")).thenReturn(false, true, true, false);
assertFalse(NewsUtils.canReferToNote("2", article, userAclIdentity));

assertTrue(NewsUtils.canReferToNote("2", article, userAclIdentity));
assertTrue(NewsUtils.canReferToNote("2", article, userAclIdentity));
assertTrue(NewsUtils.canReferToNote("2", article, userAclIdentity));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
<description>Content Feature enablement flag</description>
<property name="exo.feature.newPublicationDrawer.enabled"
value="${exo.feature.newPublicationDrawer.enabled:false}"/>
<property name="exo.feature.articleReferInTheNotes.enabled"
value="${exo.feature.articleReferInTheNotes.enabled:false}"/>
</properties-param>
</init-params>
</component>
Expand Down
3 changes: 3 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 @@ -296,6 +296,9 @@
<depends>
<module>NotesPublication</module>
</depends>
<depends>
<module>NotesTreeview</module>
</depends>
<depends>
<module>vue</module>
</depends>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@

<script type="text/javascript" id="contentHeadScripts">
eXo.env.portal.newPublicationDrawerEnabled = <%=featureService.isFeatureActiveForUser("newPublicationDrawer", userName)%>;
eXo.env.portal.referArticleEnabled = <%=featureService.isFeatureActiveForUser("articleReferInTheNotes", userName)%>;
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
:news-type="newsType"
:show-edit-button="showEditButton"
:show-publish-button="showPublishButton"
:show-refer-button="showReferButton"
:show-delete-button="showDeleteButton"
:translations="translations"
:selected-translation="selectedTranslation"
Expand All @@ -42,6 +43,7 @@ export default {
showEditButton: false,
showPublishButton: false,
showDeleteButton: false,
showReferButton: false,
selectedTranslation: {value: eXo.env.portal.language},
translations: [],
languages: [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
:show-delete-button="showDeleteButton"
:show-publish-button="showPublishButton"
:show-copy-link-button="showCopyLinkButton"
:show-refer-button="showReferButton"
@delete-article="deleteConfirmDialog"
@edit-article="editLink"
@open-publication-drawer="openPublicationDrawer" />
Expand Down Expand Up @@ -77,6 +78,14 @@
:news="news"
@edit-article="editLink"
@delete-article="deleteConfirmDialog" />
<note-treeview-drawer
:settings="{
saveButtonLabel: $t('content.article.refer.label'),
drawerTitle: $t('content.article.refer.to.note'),
showCurrentDestination: false,
spaceDisplayName: currentSpace?.displayName
}"
ref="noteTreeview" />
</div>
</v-app>
</template>
Expand Down Expand Up @@ -127,6 +136,10 @@ export default {
required: false,
default: false
},
showReferButton: {
type: Boolean,
default: false
},
translations: {
type: Array,
default: () => {
Expand Down Expand Up @@ -157,7 +170,8 @@ export default {
},
iframelyOriginRegex: /^https?:\/\/if-cdn.com/,
isPublishing: false,
allowedTargets: []
allowedTargets: [],
articlePage: null
};
},
computed: {
Expand Down Expand Up @@ -186,6 +200,7 @@ export default {
}
this.$root.$emit('application-loaded');
}
this.getArticlePage();
window.addEventListener('message', (event) => {
if (this.iframelyOriginRegex.exec(event.origin)) {
const data = JSON.parse(event.data);
Expand All @@ -195,13 +210,53 @@ export default {
}
});
this.$root.$on('open-edit-publishing-drawer', this.openPublicationDrawer);
this.$root.$on('refer-article-to-note', this.referArticle);
this.$root.$on('move-page', this.moveArticlePage);
},
methods: {
moveArticlePage(page, newParentPage) {
const previousParentPageId = page.parentPageId;
page.parentPageId = newParentPage.id;
this.news.referred = true;
this.$refs.noteTreeview.isLoading = true;
return this.$newsServices.updateNews(this.news, false, this.$newsConstants.newsObjectType.ARTICLE,
this.$newsConstants.newsUpdateType.PAGE_REFERENCE).then(() => {
return this.$newsServices.moveArticlePage(page, newParentPage).then(() => {
this.news.deReferPageId = previousParentPageId;
this.$refs.noteTreeview.isLoading = true;
this.$refs.noteTreeview.close();
this.$root.$emit('alert-message', this.$t('content.article.referred.success'), 'success');
});
}).catch(() => {
this.$root.$emit('alert-message', this.$t('content.article.referred.error'), 'error');
});
},
referArticle() {
if (this.news.referred) {
return this.$newsServices.getArticlePage(this.news.deReferPageId).then((deReferPage) => {
this.articlePage.parentPageId = deReferPage.id;
return this.$newsServices.moveArticlePage(this.articlePage, deReferPage).then(() => {
this.news.referred = false;
return this.$newsServices.updateNews(this.news, false, this.$newsConstants.newsObjectType.ARTICLE,
this.$newsConstants.newsUpdateType.PAGE_REFERENCE).then(() => {
this.$root.$emit('alert-message', this.$t('content.article.deReferred.success'), 'success');
});
});
});
} else {
this.$refs.noteTreeview.open(this.articlePage, 'movePage');
}
},
openPublicationDrawer() {
if (this.newPublicationDrawerEnabled) {
this.$refs?.publicationDrawer?.open(this.news);
}
},
getArticlePage() {
return this.$newsServices.getArticlePage(this.news?.id || this.newsId).then((page) => {
this.articlePage = page;
});
},
getSpaceById(spaceId) {
return this.$spaceService.getSpaceById(spaceId, 'identity')
.then((space) => {
Expand Down
Loading

0 comments on commit c5d7906

Please sign in to comment.