19 package org.turro.dossier.www;
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.EnumSet;
24 import java.util.List;
26 import org.turro.string.ObjectString;
27 import org.turro.string.Strings;
28 import org.turro.action.IEntityCtrl;
29 import org.turro.action.Plugins;
30 import org.turro.attach.www.AttachCtrl;
31 import org.turro.auth.Authentication;
32 import org.turro.charts.Data;
33 import org.turro.collections.ItemOf;
34 import org.turro.collections.SetOf;
35 import org.turro.dossier.command.DossierAction;
36 import org.turro.dossier.db.DossierPU;
37 import org.turro.dossier.dossier.DossierWrapper;
38 import org.turro.dossier.dossier.ProjectContext;
39 import org.turro.dossier.dw.DWIssueModel;
40 import org.turro.dossier.dw.DWWebChart;
41 import org.turro.dossier.entity.Category;
42 import org.turro.dossier.entity.Dossier;
43 import org.turro.dossier.entity.DossierStatus;
44 import org.turro.dossier.entity.DossierType;
45 import org.turro.dossier.entity.Issue;
46 import org.turro.dossier.entity.IssueResolution;
47 import org.turro.dossier.entity.IssueStatus;
48 import org.turro.dossier.entity.IssueType;
49 import org.turro.dossier.entity.ParticipantRole;
50 import org.turro.dossier.issue.IssueWrapper;
51 import org.turro.dossier.search.CategoryResults;
52 import org.turro.elephant.context.Application;
53 import org.turro.elephant.context.ElephantContext;
54 import org.turro.elephant.context.IConstructor;
55 import org.turro.elephant.db.WhereClause;
56 import org.turro.elephant.impl.repository.Repository;
57 import org.turro.elephant.impl.repository.RepositoryFile;
58 import org.turro.elephant.web.SocialImageMap;
59 import org.turro.elephant.web.SocialNet;
60 import org.turro.entities.Entities;
61 import org.turro.file.util.FileAttach;
62 import org.turro.i18n.I_;
63 import org.turro.indicator.Statistics;
64 import org.turro.jpa.entity.EntityWebUrls;
65 import org.turro.jpa.iterator.DaoHtmlIterator;
66 import org.turro.jpa.search.DaoHtmlSearch;
67 import org.turro.jpa.search.DaoSearchKey;
68 import org.turro.mail.recipients.MailContact;
69 import org.turro.marker.ElephantMarker;
70 import org.turro.marker.MarkerHelper;
71 import org.turro.math.Numbers;
72 import org.turro.participation.ParticipationReason;
73 import org.turro.phase.PhaseDefinitions;
74 import org.turro.plugin.contacts.ContactList;
75 import org.turro.plugin.contacts.IContact;
76 import org.turro.polls.PollsCtrl;
77 import org.turro.tags.TagCloud;
78 import org.turro.util.Arrays;
79 import org.turro.visual.DossierVisualElements;
80 import org.turro.visual.VisualElements;
81 import org.turro.www.commentit.CommentItCtrl;
82 import org.turro.www.describeit.DescribeItCtrl;
83 import org.turro.www.starit.StarItCtrl;
84 import org.turro.www.voteit.VoteItCtrl;
92 private final String pubPath, uniqueId;
93 private String actualParameters, allowedCategories, issuePath, pendingWorths;
94 private long categoryId, dossierId, lastCategoryId = -1;
95 private List<String> dossierTypes, dossierStatus, projectPhases;
96 private boolean showSubject;
97 private boolean all, direct;
98 private Collection<IContact> related;
107 this.pubPath = pubPath;
108 this.uniqueId = uniqueId;
113 this.categoryId = categoryId;
117 this.dossierId = dossierId;
120 void setDossierTypes(List<String> dossierTypes) {
121 this.dossierTypes = dossierTypes;
125 this.dossierStatus = dossierStatus;
129 return projectPhases;
133 this.projectPhases = projectPhases;
141 this.showSubject = showSubject;
145 this.allowedCategories = allowedCategories;
153 this.direct = direct;
157 this.related = related;
161 return pendingWorths;
165 this.pendingWorths = pendingWorths;
173 this.issuePath = issuePath;
181 this.phaseFilter = phaseFilter;
187 wc.
addClause(
"select distinct dossier from Dossier as dossier");
188 wc.
addClause(
"left outer join dossier.participants participant");
189 wc.
addClause(
"left outer join dossier.project project");
195 .setEntityFields(
"dossier",
"id")
196 .setDefaultSorting(
"dossier.description")
197 .onCriteria(w -> addCriteria(w,
true))
204 wc.
addClause(
"select count(distinct dossier) from Dossier as dossier");
205 wc.
addClause(
"left outer join dossier.participants participant");
206 wc.
addClause(
"left outer join dossier.project project");
207 addCriteria(wc,
true);
212 return Strings.isBlank(actualParameters) ?
"?a=b" : actualParameters;
216 if(obj instanceof
Issue) {
226 }
else if(obj instanceof
Dossier) {
260 prepareValues(e, page,
false);
264 actualParameters = getPageLink(page);
270 if(issueId !=
null) {
276 "jQuery('title').html('" + issue.
getFullDescription(showSubject).replace(
"'",
"\\'") +
"');"
279 prepareValues(issue, page,
false);
290 prepareValues(e, page,
false);
294 actualParameters = getPageLink(page);
305 wc.
addClause(
"select distinct dossier from Dossier as dossier");
306 wc.
addClause(
"left outer join dossier.participants participant");
307 wc.
addClause(
"left outer join dossier.project project");
308 addCriteria(wc,
true);
317 if(identifier ==
null) {
318 identifier = super.getIdentifier();
323 private void addCriteria(
WhereClause wc,
boolean filterPhase) {
330 dsk.
applyToQuery(wc, Arrays.objects(
"dossier.description"),
true);
334 PhaseHtmlFilter phf = PhaseHtmlFilter.getInstance(
constructor, ElephantContext.getContextVariable(
constructor));
335 if(phf !=
null && !phf.isEmpty()) {
336 int phase = Numbers.from(phf.getPhase(), -1).intValue();
339 wc.
addClause(
"and dossier.project.phase = :" + par);
346 wc.
addClause(
"and dossier.publishable = TRUE");
348 if(!Strings.isBlank(pendingWorths)) {
349 IContact contact = Authentication.getIContact();
351 wc.
addClause(
"select v from WorthValue v");
352 wc.
addClause(
"where v.dossier = dossier");
353 wc.
addClause(
"and v.worthDefinition.id in (" + pendingWorths +
")");
354 wc.
addClause(
"and v.idContact = :pendContact");
359 wc.
addClause(
"and dossier.category.id in (" + getCategories(categoryId) +
")");
360 }
else if(dossierId > 0) {
361 wc.
addClause(
"and dossier.id = " + dossierId);
362 }
else if(!Strings.isBlank(allowedCategories)) {
364 String selCat = CategoriesTree.getSelectedItem(
constructor, ElephantContext.getContextVariable(
constructor));
365 if(!Strings.isBlank(selCat)) {
366 wc.
addClause(
"and dossier.category.fullDescription like '" + Category.getPathToFullDescription(selCat +
"%'"));
369 if(!
"all".equals(allowedCategories)) {
370 CategoryResults.addExistsCategoryAffiliance(wc, allowedCategories,
"dossier");
373 if(dossierTypes !=
null && dossierTypes.size() > 0) {
374 wc.
addClause(
"and dossier.type in (:types)");
375 wc.
addNamedValue(
"types", Arrays.fromCollection(dossierTypes).map(t -> typeValue((String) t)));
377 if(dossierStatus !=
null && dossierStatus.size() > 0) {
378 wc.
addClause(
"and dossier.status in (:status)");
379 wc.
addNamedValue(
"status", Arrays.fromCollection(dossierStatus).map(t -> statusValue((String) t)));
382 if(projectPhases !=
null && !projectPhases.isEmpty()) {
383 List<Integer> indexes = PhaseDefinitions.instance().stream()
384 .filter(pd -> pd.anyStringMatch(projectPhases))
385 .map(pd -> pd.getIndex()).toList();
386 wc.
addClause(
"and dossier.project.phase in (:phases)");
391 wc.
addIn(
"and",
"dossier.id", TagCloud.getIdentifiersAsLong(
constructor,
"dossier"));
400 return super.isValid(e);
409 private String getCategories(
long categoryId) {
410 String result =
null;
412 return addCategory(category, result);
415 private String addCategory(Category category, String result) {
416 if(category !=
null) {
417 result = (String) (((result ==
null) ?
"" : result +
",") + category.getId());
418 for(Category c : category.getChildren()) {
419 result = addCategory(c, result);
425 private void prepareValues(
final Dossier dossier,
int page,
boolean asMail) {
426 DossierWrapper dw =
new DossierWrapper(dossier);
428 marker.
put(
"iee", Entities.getController(dossier));
430 if(asMail && pubPath !=
null) {
431 marker.
put(
"name", MailContact.createLink(dossier.getDescription(), getItemLink(dossier, page),
false));
433 marker.
put(
"name", dossier.getDescription());
435 String link = getItemLink(dossier, page);
440 if(!Strings.isBlank(pubPath)) {
441 marker.
put(
"readall", getItemLink(dossier, page));
444 (dossier.getStatus().equals(DossierStatus.DOSSIER_OPENED) ?
" openned" :
"") +
445 (dossier.getStatus().equals(DossierStatus.DOSSIER_CLOSED) ?
" closed" :
"") +
446 (dossier.getStatus().equals(DossierStatus.DOSSIER_FROZEN) ?
" frozen" :
""));
447 if(!Strings.isBlank(issuePath)) {
448 marker.
put(
"issuePath", ElephantContext.getRootWebPath() + issuePath);
449 }
else if(dw.getCanShowAllIssues()) {
450 marker.
put(
"issuePath", ElephantContext.getRootWebPath() +
"/user/kbase");
454 if(dossier.getType().isVotes()) {
456 vic.setEntityPath(DossierPU.getObjectPath(dossier));
457 vic.setForbiden(!dossier.getStatus().isOpen());
458 if(dossier.getType().isSecret()) {
460 vic.setAllowed((ContactList) dossier.getFullParticipants().getVoteIParticipants());
467 sic.setEntityPath(DossierPU.getObjectPath(dossier));
471 CommentItCtrl cic =
new CommentItCtrl(
constructor);
472 cic.setEntityPath(DossierPU.getObjectPath(dossier));
477 ac.setEntityPath(DossierPU.getObjectPath(dossier));
478 ac.setPublicOnly(
true);
479 IContact contact = Authentication.getIContact();
480 ac.addRestrictedFolders(dossier.getFullParticipants().getParticipationStrings(contact));
484 DescribeItCtrl dic =
new DescribeItCtrl(
constructor);
485 dic.setEntityPath(DossierPU.getObjectPath(dossier));
489 pollc.setEntityPath(DossierPU.getObjectPath(dossier));
492 final DWIssueModel issueModel =
new DWIssueModel();
493 issueModel.setDossierId(dossier.getId());
497 protected void onCreate(Data data, Object[] pars) {
498 data.setLink(ElephantContext.getRootWebPath() + KnowledgeBaseDashboard.createLink(
"*",
false,
499 (Set<IssueType>) EnumSet.of((IssueType) pars[0]),
null,
null, dossier.getId()));
502 protected void loadData() {
503 setData(I_.get(
"Type"), issueModel.getByType());
509 protected void onCreate(Data data, Object[] pars) {
510 data.setLink(ElephantContext.getRootWebPath() + KnowledgeBaseDashboard.createLink(
"*",
false,
null,
511 (Set<IssueStatus>) EnumSet.of((IssueStatus) pars[0]),
null, dossier.getId()));
514 protected void loadData() {
515 setData(I_.get(
"Status"), issueModel.getByStatus());
519 DWWebChart resolution =
new DWWebChart(
constructor) {
521 protected void onCreate(Data data, Object[] pars) {
522 data.setLink(ElephantContext.getRootWebPath() + KnowledgeBaseDashboard.createLink(
"*",
false,
null,
null,
523 (Set<IssueResolution>) EnumSet.of((IssueResolution) pars[0]), dossier.getId()));
526 protected void loadData() {
527 setData(I_.get(
"Resolution"), issueModel.getByResolution());
530 marker.
put(
"resolutionChart", resolution);
532 marker.
put(
"actions",
new DossierAction());
534 marker.
put(
"files",
new FileAttach(DossierPU.getObjectPath(dossier)));
535 marker.
put(
"projectContext",
new ProjectContext());
536 marker.
put(
"dve", DossierVisualElements.load());
539 IEntityCtrl ec = Plugins.loadImplementation(IEntityCtrl.class,
"students-ctrl");
542 ec.setEntityPath(DossierPU.getObjectPath(dossier));
547 IEntityCtrl ecf = Plugins.loadImplementation(IEntityCtrl.class,
"forum-ctrl");
550 ecf.setEntityPath(DossierPU.getObjectPath(dossier));
551 ecf.setTemplate(
"related");
557 if(dw.getCanShowAllIssues()) {
558 marker.
put(
"createIssue", CreateIssueCtrl.linkToCreateIssue(link, dossier.getId() +
"",
null));
562 private void prepareValues(Issue issue,
int page,
boolean asMail) {
563 marker.
put(
"wrapper",
new IssueWrapper(issue));
564 marker.
put(
"iee", Entities.getController(issue));
567 Dossier dossier = issue.getDossier();
568 if(dossier.getType().isVotes()) {
570 vic.setEntityPath(DossierPU.getObjectPath(issue));
571 vic.setForbiden(issue.getStatus().isFinished());
572 if(dossier.getType().isSecret()) {
574 vic.setAllowed((ContactList) dossier.getFullParticipants().getVoteIParticipants());
581 sic.setEntityPath(DossierPU.getObjectPath(issue));
585 CommentItCtrl cic =
new CommentItCtrl(
constructor);
586 cic.setEntityPath(DossierPU.getObjectPath(issue));
591 ac.setEntityPath(DossierPU.getObjectPath(issue));
592 ac.setPublicOnly(
true);
593 IContact contact = Authentication.getIContact();
594 ac.addRestrictedFolders(issue.getDossier().getFullParticipants().getParticipationStrings(contact));
598 DescribeItCtrl dic =
new DescribeItCtrl(
constructor);
599 dic.setEntityPath(DossierPU.getObjectPath(issue));
602 marker.
put(
"files",
new FileAttach(DossierPU.getObjectPath(issue)));
605 private String getItemLink(Dossier dossier,
int page) {
606 if(pubPath ==
null) {
607 String link = dossier.getDossierURL();
611 return ElephantContext.getRootWebPath() + link;
614 String ewu = EntityWebUrls.getUrlFromEntity(dossier);
616 return pubPath + ewu;
618 return pubPath +
"?" + MarkerHelper.setObfuscatedPars(
"item=" + dossier.getId());
623 private String getPageLink(
int page) {
624 return pubPath +
"?page=" + page;
637 ArrayList<RepositoryFile> files =
new ArrayList<>();
638 String path = getItemLink(e, 0);
657 if(contact ==
null || !contact.
isValid()) {
661 wc.
addClause(
"participant.idContact = :idContact");
663 wc.
addClause(
"and (participant.role = :cpdrole1 or participant.role = :cpdrole2)");
664 wc.
addNamedValue(
"cpdrole1", ParticipantRole.PARTICIPANT_OWNER);
665 wc.
addNamedValue(
"cpdrole2", ParticipantRole.PARTICIPANT_ASSISTANT);
668 }
else if(related !=
null) {
669 if(related.isEmpty()) {
673 wc.
addClause(
"participant.idContact in (:idContact)");
674 wc.
addNamedValue(
"idContact",
new SetOf<IContact, String>(related,
new ItemOf<IContact, String>() {
676 public String getFrom(IContact e) {
680 wc.
addClause(
"and (participant.role = :cpdrole1 or participant.role = :cpdrole2)");
681 wc.
addNamedValue(
"cpdrole1", ParticipantRole.PARTICIPANT_OWNER);
682 wc.
addNamedValue(
"cpdrole2", ParticipantRole.PARTICIPANT_ASSISTANT);
685 }
else if(
isRestricted() && !Application.getApplication().isInRole(
"dossier:all")) {
686 IContact contact = Authentication.getIContact();
687 if(contact ==
null || !contact.isValid()) {
691 wc.
addClause(
"participant.idContact = :idContact");
693 wc.
addClause(
"and (participant.role = :cpdrole1 or participant.role = :cpdrole2)");
694 wc.
addNamedValue(
"cpdrole1", ParticipantRole.PARTICIPANT_OWNER);
695 wc.
addNamedValue(
"cpdrole2", ParticipantRole.PARTICIPANT_ASSISTANT);
697 CategoryResults.addParticipantAffiliance(wc,
"or", contact.getId(),
"dossier");
705 private DossierType typeValue(String name) {
706 return DossierType.valueOf(name);
709 private DossierStatus statusValue(String name) {
710 return DossierStatus.valueOf(name);
void addRestrictedFolders(HashSet< String > restrictedFolders)
void setPublicOnly(boolean publicOnly)
void setEntityPath(String entityPath)
static IContact getIContact()
static String getObjectPath(Object object)
boolean getCanShowAllAttachments()
String getFullDescription()
ParticipantSet< IDossierParticipant > getFullParticipants()
String getFullDescription()
static String createIssue(String link, String dossierId, String template)
List< String > getProjectPhases()
Dossier entity(Long value)
DossierIterator(IConstructor constructor, String pubPath, String uniqueId)
WhereClause getCountClause()
AttachCtrl getAttachments(Object obj)
boolean isValid(Dossier e)
void setAllowedCategories(String allowedCategories)
Collection< String > metas(Dossier e)
DossierIterator(IConstructor constructor, boolean mail, String pubPath, String uniqueId)
void setPhaseFilter(PhaseHtmlFilter phaseFilter)
void setProjectPhases(List< String > projectPhases)
void setCategoryId(long categoryId)
void renderSummary(ElephantMarker marker, Dossier e, int page)
void renderItem(ElephantMarker marker, Dossier e, int page)
void setDirect(boolean direct)
WhereClause getWhereClause()
Object getParticipationCtrl(Dossier dossier, ParticipationReason reason)
void setIssuePath(String issuePath)
void setShowSubject(boolean showSubject)
String getPendingWorths()
PhaseHtmlFilter getPhaseFilter()
void setRelated(Collection< IContact > related)
String getCreateIssueCtrl(String link, Dossier dossier, String template)
void setDossierId(long dossierId)
String getAddInformationCtrl(String link, Issue issue, String template)
String getActualParameters()
void setPendingWorths(String pendingWorths)
VisualElements loadVisuals()
void setDossierStatus(List< String > dossierStatus)
boolean isInRole(String role)
static Application getApplication()
static String getContextVariable(IConstructor constructor)
void addClause(String clause)
void addIn(String operator, String field, List values)
void addNamedValue(String name, Object value)
Set< RepositoryFile > getRepositoryFiles(String pattern)
static boolean hasImage(String url)
List< String > getMetas()
static IElephantEntity getController(String path)
Repository getPublishableRepository(IConstructor constructor)
static Statistics load(IConstructor constructor, String rankingInstance, String matchingInstance, WhereClause wc)
Object getSingleResultOrNull(SqlClause sc)
ID getIDFromURL(String root)
boolean isAllowAttachments()
boolean isAllowMatching()
String getSummaryTemplate()
boolean isAllowInterest()
boolean isAllowDescriptions()
boolean isAllowComments()
static DaoHtmlSearch getInstance(IConstructor constructor, String context)
boolean applyToQuery(WhereClause wc, List< String > fields, boolean withSynonyms)
void process(String rootTmpl, String tmpl)
Object put(Object key, Object value)
static DossierVisualElements load()
void addOnLoadedJavaScript(String script)
String getParameter(String param)
Object getParticipationControl(IConstructor constructor, ParticipationReason reason)