Skip to content
Snippets Groups Projects
Commit de67eb27 authored by uhensler's avatar uhensler
Browse files

OO-4080: Export an efficiency statement as a PDF file

parent 62155358
No related branches found
No related tags found
No related merge requests found
Showing
with 80 additions and 27 deletions
...@@ -290,8 +290,8 @@ $r.renderForce("development") ...@@ -290,8 +290,8 @@ $r.renderForce("development")
</div> </div>
</div> </div>
<div id="o_container_page_width_toggler"> <div id="o_container_page_width_toggler">
<div id="o_go_standard_width" title="$r.translateInAttribute("content.width.standard")" class="btn btn-primary btn-xs"><i class="o_icon o_icon_width_collapse o_icon-fw"> </i></div> <div id="o_go_standard_width" title="$r.translateInAttribute("content.width.standard")" class="btn btn-primary btn-xs o_noprint"><i class="o_icon o_icon_width_collapse o_icon-fw"> </i></div>
<div id="o_go_full_width" title="$r.translateInAttribute("content.width.standard")" class="btn btn-default btn-xs"><i class="o_icon o_icon_width_expand o_icon-fw"> </i></div> <div id="o_go_full_width" title="$r.translateInAttribute("content.width.standard")" class="btn btn-default btn-xs o_noprint"><i class="o_icon o_icon_width_expand o_icon-fw"> </i></div>
</div> </div>
<div><script type="text/javascript"> <div><script type="text/javascript">
/* <![CDATA[ */ /* <![CDATA[ */
......
...@@ -22,10 +22,13 @@ package org.olat.course.assessment.ui.tool; ...@@ -22,10 +22,13 @@ package org.olat.course.assessment.ui.tool;
import java.util.List; import java.util.List;
import org.olat.basesecurity.BaseSecurity; import org.olat.basesecurity.BaseSecurity;
import org.olat.core.commons.services.pdf.PdfModule;
import org.olat.core.commons.services.pdf.PdfService;
import org.olat.core.gui.UserRequest; import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.Component; import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.link.Link;
import org.olat.core.gui.components.link.LinkFactory; import org.olat.core.gui.components.link.LinkFactory;
import org.olat.core.gui.components.stack.TooledController;
import org.olat.core.gui.components.stack.TooledStackedPanel; import org.olat.core.gui.components.stack.TooledStackedPanel;
import org.olat.core.gui.components.stack.TooledStackedPanel.Align; import org.olat.core.gui.components.stack.TooledStackedPanel.Align;
import org.olat.core.gui.components.velocity.VelocityContainer; import org.olat.core.gui.components.velocity.VelocityContainer;
...@@ -33,12 +36,15 @@ import org.olat.core.gui.control.Controller; ...@@ -33,12 +36,15 @@ import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.Event; import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.controller.BasicController; import org.olat.core.gui.control.controller.BasicController;
import org.olat.core.gui.control.creator.ControllerCreator;
import org.olat.core.gui.control.generic.closablewrapper.CloseableCalloutWindowController; import org.olat.core.gui.control.generic.closablewrapper.CloseableCalloutWindowController;
import org.olat.core.gui.media.MediaResource;
import org.olat.core.id.Identity; import org.olat.core.id.Identity;
import org.olat.core.id.IdentityEnvironment; import org.olat.core.id.IdentityEnvironment;
import org.olat.core.id.Roles; import org.olat.core.id.Roles;
import org.olat.core.id.context.ContextEntry; import org.olat.core.id.context.ContextEntry;
import org.olat.core.id.context.StateEntry; import org.olat.core.id.context.StateEntry;
import org.olat.core.util.FileUtils;
import org.olat.course.CourseFactory; import org.olat.course.CourseFactory;
import org.olat.course.ICourse; import org.olat.course.ICourse;
import org.olat.course.assessment.ui.tool.event.CourseNodeEvent; import org.olat.course.assessment.ui.tool.event.CourseNodeEvent;
...@@ -60,12 +66,13 @@ import org.springframework.beans.factory.annotation.Autowired; ...@@ -60,12 +66,13 @@ import org.springframework.beans.factory.annotation.Autowired;
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
* *
*/ */
public class AssessmentIdentityCourseController extends BasicController implements AssessedIdentityController { public class AssessmentIdentityCourseController extends BasicController
implements AssessedIdentityController, TooledController {
private final TooledStackedPanel stackPanel; private final TooledStackedPanel stackPanel;
private final VelocityContainer identityAssessmentVC; private final VelocityContainer identityAssessmentVC;
private Link nextLink, previousLink, courseNodeSelectionLink; private Link nextLink, previousLink, courseNodeSelectionLink;
private Link pdfLink;
private IdentityCertificatesController certificateCtrl; private IdentityCertificatesController certificateCtrl;
private AssessedIdentityLargeInfosController infosController; private AssessedIdentityLargeInfosController infosController;
...@@ -81,9 +88,13 @@ public class AssessmentIdentityCourseController extends BasicController implemen ...@@ -81,9 +88,13 @@ public class AssessmentIdentityCourseController extends BasicController implemen
@Autowired @Autowired
private BaseSecurity securityManager; private BaseSecurity securityManager;
@Autowired
private PdfModule pdfModule;
@Autowired
private PdfService pdfService;
public AssessmentIdentityCourseController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel, public AssessmentIdentityCourseController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel,
RepositoryEntry courseEntry, UserCourseEnvironment coachCourseEnv, Identity assessedIdentity) { RepositoryEntry courseEntry, UserCourseEnvironment coachCourseEnv, Identity assessedIdentity, boolean nodeSelectable) {
super(ureq, wControl); super(ureq, wControl);
this.stackPanel = stackPanel; this.stackPanel = stackPanel;
...@@ -110,7 +121,7 @@ public class AssessmentIdentityCourseController extends BasicController implemen ...@@ -110,7 +121,7 @@ public class AssessmentIdentityCourseController extends BasicController implemen
listenTo(certificateCtrl); listenTo(certificateCtrl);
} }
treeOverviewCtrl = new IdentityAssessmentOverviewController(ureq, getWindowControl(), assessedUserCourseEnv, true, false, true); treeOverviewCtrl = new IdentityAssessmentOverviewController(ureq, getWindowControl(), assessedUserCourseEnv, nodeSelectable, false, true);
listenTo(treeOverviewCtrl); listenTo(treeOverviewCtrl);
identityAssessmentVC.put("courseOverview", treeOverviewCtrl.getInitialComponent()); identityAssessmentVC.put("courseOverview", treeOverviewCtrl.getInitialComponent());
...@@ -126,6 +137,15 @@ public class AssessmentIdentityCourseController extends BasicController implemen ...@@ -126,6 +137,15 @@ public class AssessmentIdentityCourseController extends BasicController implemen
protected void doDispose() { protected void doDispose() {
// //
} }
@Override
public void initTools() {
if (pdfModule.isEnabled()) {
pdfLink = LinkFactory.createToolLink("output.pdf", translate("output.pdf"), this);
pdfLink.setIconLeftCSS("o_icon o_icon-fw o_icon_tool_pdf");
stackPanel.addTool(pdfLink, Align.right, false);
}
}
@Override @Override
public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) { public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) {
...@@ -179,6 +199,8 @@ public class AssessmentIdentityCourseController extends BasicController implemen ...@@ -179,6 +199,8 @@ public class AssessmentIdentityCourseController extends BasicController implemen
doNextNode(ureq); doNextNode(ureq);
} else if(courseNodeSelectionLink == source) { } else if(courseNodeSelectionLink == source) {
doSelectCourseNode(ureq); doSelectCourseNode(ureq);
} else if (source == pdfLink) {
doExportPdf(ureq);
} }
} }
...@@ -299,4 +321,28 @@ public class AssessmentIdentityCourseController extends BasicController implemen ...@@ -299,4 +321,28 @@ public class AssessmentIdentityCourseController extends BasicController implemen
} }
return false; return false;
} }
private void doExportPdf(UserRequest ureq) {
ControllerCreator printControllerCreator = (lureq, lwControl) -> {
return new AssessmentIdentityCourseController(lureq, lwControl, stackPanel,
courseEntry, coachCourseEnv, assessedIdentity, false);
};
String title = getPdfTitle();
MediaResource resource = pdfService.convert(title, getIdentity(), printControllerCreator, getWindowControl());
ureq.getDispatchResult().setResultingMediaResource(resource);
}
private String getPdfTitle() {
StringBuilder sb = new StringBuilder();
sb.append(translate("output.pdf.prefix.user"));
sb.append("_");
sb.append(courseEntry.getDisplayname());
sb.append("_");
sb.append(assessedIdentity.getUser().getLastName());
sb.append("_");
sb.append(assessedIdentity.getUser().getFirstName());
sb.append("_");
return FileUtils.normalizeFilename(sb.toString());
}
} }
\ No newline at end of file
...@@ -785,7 +785,7 @@ public class IdentityListCourseNodeController extends FormBasicController ...@@ -785,7 +785,7 @@ public class IdentityListCourseNodeController extends FormBasicController
WindowControl bwControl = addToHistory(ureq, ores, null); WindowControl bwControl = addToHistory(ureq, ores, null);
if(courseNode.getParent() == null) { if(courseNode.getParent() == null) {
currentIdentityCtrl = new AssessmentIdentityCourseController(ureq, bwControl, stackPanel, currentIdentityCtrl = new AssessmentIdentityCourseController(ureq, bwControl, stackPanel,
courseEntry, coachCourseEnv, assessedIdentity); courseEntry, coachCourseEnv, assessedIdentity, true);
} else { } else {
currentIdentityCtrl = new AssessmentIdentityCourseNodeController(ureq, getWindowControl(), stackPanel, currentIdentityCtrl = new AssessmentIdentityCourseNodeController(ureq, getWindowControl(), stackPanel,
courseEntry, courseNode, coachCourseEnv, assessedIdentity, true); courseEntry, courseNode, coachCourseEnv, assessedIdentity, true);
......
...@@ -44,6 +44,8 @@ groups=Gruppen ...@@ -44,6 +44,8 @@ groups=Gruppen
msg.certificate.pending=$org.olat.course.certificate.ui\:msg.certificate.pending msg.certificate.pending=$org.olat.course.certificate.ui\:msg.certificate.pending
no.certificate=Kein Zertifikat vorhanden no.certificate=Kein Zertifikat vorhanden
overview=\u00DCbersicht overview=\u00DCbersicht
output.pdf=PDF exportieren
output.pdf.prefix.user=Leistungsnachweis
participantgroups.title=Teilnehmer in Gruppen participantgroups.title=Teilnehmer in Gruppen
previous=Zur\u00FCck previous=Zur\u00FCck
reopen=$org.olat.modules.assessment.ui\:reopen reopen=$org.olat.modules.assessment.ui\:reopen
......
...@@ -44,6 +44,8 @@ groups=Groups ...@@ -44,6 +44,8 @@ groups=Groups
msg.certificate.pending=$org.olat.course.certificate.ui\:msg.certificate.pending msg.certificate.pending=$org.olat.course.certificate.ui\:msg.certificate.pending
no.certificate=No certificate available no.certificate=No certificate available
overview=Overview overview=Overview
output.pdf=Export PDF
output.pdf.prefix.user=Efficiency statement
participantgroups.title=Participants in groups participantgroups.title=Participants in groups
previous=Previous previous=Previous
reopen=$org.olat.modules.assessment.ui\:reopen reopen=$org.olat.modules.assessment.ui\:reopen
......
...@@ -61,7 +61,7 @@ public class MemberListController extends AbstractMemberListController { ...@@ -61,7 +61,7 @@ public class MemberListController extends AbstractMemberListController {
Identity assessedIdentity = securityManager.loadIdentityByKey(member.getIdentityKey()); Identity assessedIdentity = securityManager.loadIdentityByKey(member.getIdentityKey());
identityAssessmentController = new AssessmentIdentityCourseController(ureq, getWindowControl(), toolbarPanel, identityAssessmentController = new AssessmentIdentityCourseController(ureq, getWindowControl(), toolbarPanel,
repoEntry, coachCourseEnv, assessedIdentity); repoEntry, coachCourseEnv, assessedIdentity, true);
listenTo(identityAssessmentController); listenTo(identityAssessmentController);
String displayName = userManager.getUserDisplayName(assessedIdentity); String displayName = userManager.getUserDisplayName(assessedIdentity);
......
...@@ -98,7 +98,7 @@ public class MemberListWithOriginFilterController extends AbstractMemberListCont ...@@ -98,7 +98,7 @@ public class MemberListWithOriginFilterController extends AbstractMemberListCont
Identity assessedIdentity = securityManager.loadIdentityByKey(member.getIdentityKey()); Identity assessedIdentity = securityManager.loadIdentityByKey(member.getIdentityKey());
identityAssessmentController = new AssessmentIdentityCourseController(ureq, getWindowControl(), toolbarPanel, identityAssessmentController = new AssessmentIdentityCourseController(ureq, getWindowControl(), toolbarPanel,
repoEntry, coachCourseEnv, assessedIdentity); repoEntry, coachCourseEnv, assessedIdentity, true);
listenTo(identityAssessmentController); listenTo(identityAssessmentController);
String displayName = userManager.getUserDisplayName(assessedIdentity); String displayName = userManager.getUserDisplayName(assessedIdentity);
......
...@@ -86,7 +86,7 @@ public class MemberSearchController extends AbstractMemberListController { ...@@ -86,7 +86,7 @@ public class MemberSearchController extends AbstractMemberListController {
Identity assessedIdentity = securityManager.loadIdentityByKey(member.getIdentityKey()); Identity assessedIdentity = securityManager.loadIdentityByKey(member.getIdentityKey());
identityAssessmentController = new AssessmentIdentityCourseController(ureq, getWindowControl(), toolbarPanel, identityAssessmentController = new AssessmentIdentityCourseController(ureq, getWindowControl(), toolbarPanel,
repoEntry, coachCourseEnv, assessedIdentity); repoEntry, coachCourseEnv, assessedIdentity, true);
listenTo(identityAssessmentController); listenTo(identityAssessmentController);
String displayName = userManager.getUserDisplayName(assessedIdentity); String displayName = userManager.getUserDisplayName(assessedIdentity);
......
...@@ -268,7 +268,7 @@ public class UserDetailsController extends BasicController implements Activateab ...@@ -268,7 +268,7 @@ public class UserDetailsController extends BasicController implements Activateab
if(assessmentCtrl == null) { if(assessmentCtrl == null) {
RepositoryEntry entry = statementEntry.getCourse(); RepositoryEntry entry = statementEntry.getCourse();
UserCourseEnvironment coachCourseEnv = loadUserCourseEnvironment(ureq, entry); UserCourseEnvironment coachCourseEnv = loadUserCourseEnvironment(ureq, entry);
assessmentCtrl = new AssessmentIdentityCourseController(ureq, getWindowControl(), stackPanel, entry, coachCourseEnv, assessedIdentity); assessmentCtrl = new AssessmentIdentityCourseController(ureq, getWindowControl(), stackPanel, entry, coachCourseEnv, assessedIdentity, true);
listenTo(assessmentCtrl); listenTo(assessmentCtrl);
} }
mainVC.put("segmentCmp", assessmentCtrl.getInitialComponent()); mainVC.put("segmentCmp", assessmentCtrl.getInitialComponent());
......
...@@ -3,10 +3,10 @@ ...@@ -3,10 +3,10 @@
#if ($hasPortrait) #if ($hasPortrait)
#if ($canLinkToHomePage) #if ($canLinkToHomePage)
<a href="javascript:void(o_openPopUp('$r.commandURI("showuserinfo")', '${identityKey}', '900', '600', false))"> <a href="javascript:void(o_openPopUp('$r.commandURI("showuserinfo")', '${identityKey}', '900', '600', false))">
<img src="$r.staticLink("images/transparent.gif")" alt="$altText" title="$altText" class="$portraitCssClass" style="background-image : url('$mapperUrl');" /> <img src="$r.staticLink("images/transparent.gif")" alt="$altText" title="$altText" class="$portraitCssClass" style="background-image : url('$mapperUrl') !important; background-repeat: no-repeat !important;" />
</a> </a>
#else #else
<img src="$r.staticLink("images/transparent.gif")" alt="$altText" title="$altText" class="$portraitCssClass" style="background-image : url('$mapperUrl');" /> <img src="$r.staticLink("images/transparent.gif")" alt="$altText" title="$altText" class="$portraitCssClass" style="background-image : url('$mapperUrl') !important; background-repeat: no-repeat !important;" />
#end #end
#else #else
#if ($canLinkToHomePage) #if ($canLinkToHomePage)
......
...@@ -318,6 +318,7 @@ $fa-css-prefix: "o_icon" !default; ...@@ -318,6 +318,7 @@ $fa-css-prefix: "o_icon" !default;
.o_icon_toggle_off:before { content: $fa-var-toggle-off; } .o_icon_toggle_off:before { content: $fa-var-toggle-off; }
.o_icon_to_read:before { content: $fa-var-circle; } .o_icon_to_read:before { content: $fa-var-circle; }
.o_icon_tool:before { content: $fa-var-gear; } .o_icon_tool:before { content: $fa-var-gear; }
.o_icon_tool_pdf:before { content: $fa-var-file-pdf-o; }
.o_icon_tools:before { content: $fa-var-wrench; } .o_icon_tools:before { content: $fa-var-wrench; }
.o_icon_top:before { content: $fa-var-chevron-up; } .o_icon_top:before { content: $fa-var-chevron-up; }
.o_icon_translation_item:before { content: $fa-var-file-code-o; } .o_icon_translation_item:before { content: $fa-var-file-code-o; }
......
...@@ -274,26 +274,28 @@ Dummy is used for registered users which have no personal avatar image. ...@@ -274,26 +274,28 @@ Dummy is used for registered users which have no personal avatar image.
- dummy_male is used for male users - dummy_male is used for male users
Anonymous is used for guest users and in anonymous chat / forum postings Anonymous is used for guest users and in anonymous chat / forum postings
The "important!" avoids hiding the image by bootstrap.
*/ */
.o_portrait_avatar, .o_portrait_avatar,
.o_portrait_dummy, .o_portrait_dummy,
.o_portrait_dummy_female_big, .o_portrait_dummy_female_big,
.o_portrait_dummy_male_big, .o_portrait_dummy_male_big,
.o_portrait_anonymous {width: 100px; height: 100px;} .o_portrait_anonymous {width: 100px; height: 100px;}
.o_portrait_dummy {background-image: url('#{$o-images-path}portrait/dummy.png');} .o_portrait_dummy {background-image: url('#{$o-images-path}portrait/dummy.png') !important;}
.o_portrait_dummy_female_big {background-image: url('#{$o-images-path}portrait/dummy_female_big.png');} .o_portrait_dummy_female_big {background-image: url('#{$o-images-path}portrait/dummy_female_big.png') !important;}
.o_portrait_dummy_male_big {background-image: url('#{$o-images-path}portrait/dummy_male_big.png');} .o_portrait_dummy_male_big {background-image: url('#{$o-images-path}portrait/dummy_male_big.png') !important;}
.o_portrait_anonymous {background-image: url('#{$o-images-path}portrait/anonymous.png'); } .o_portrait_anonymous {background-image: url('#{$o-images-path}portrait/anonymous.png') !important; }
.o_portrait_avatar_small, .o_portrait_avatar_small,
.o_portrait_dummy_small, .o_portrait_dummy_small,
.o_portrait_dummy_female_small, .o_portrait_dummy_female_small,
.o_portrait_dummy_male_small, .o_portrait_dummy_male_small,
.o_portrait_anonymous_small {width: 30px; height: 30px;} .o_portrait_anonymous_small {width: 30px; height: 30px;}
.o_portrait_dummy_small {background-image: url('#{$o-images-path}portrait/dummy_small.png');} .o_portrait_dummy_small {background-image: url('#{$o-images-path}portrait/dummy_small.png') !important;}
.o_portrait_dummy_female_small{background-image: url('#{$o-images-path}portrait/dummy_female_small.png');} .o_portrait_dummy_female_small {background-image: url('#{$o-images-path}portrait/dummy_female_small.png') !important;}
.o_portrait_dummy_male_small {background-image: url('#{$o-images-path}portrait/dummy_male_small.png');} .o_portrait_dummy_male_small {background-image: url('#{$o-images-path}portrait/dummy_male_small.png') !important;}
.o_portrait_anonymous_small {background-image: url('#{$o-images-path}portrait/anonymous_small.png'); } .o_portrait_anonymous_small {background-image: url('#{$o-images-path}portrait/anonymous_small.png') !important; }
/* Date component, used in info course element, blog etc */ /* Date component, used in info course element, blog etc */
.o_datecomp { .o_datecomp {
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment