Skip to content
Snippets Groups Projects
Commit 12a621ed authored by srosse's avatar srosse
Browse files

Merge OpenOLAT 10.4 to OpenOLAT default branch with 485cf24f684cb459fddb61582618d7e4798dde8b

parents 19e641a0 bda48ffb
No related branches found
No related tags found
No related merge requests found
Showing
with 325 additions and 40 deletions
#Sun Dec 14 09:38:29 CET 2014
#Wed Feb 17 16:46:57 CET 2016
admin.menu.title=WebDAV
admin.menu.title.alt=Acc\u00E8s WebDAV
admin.webdav.description=Gr\u00E2ce \u00E0 WebDAV, les dossiers OpenOLAT peuvent appara\u00EEtre sur votre bureau local et \u00EAtre utilis\u00E9s. Vous devez configurer cette fonction pour la rendre disponible \u00E0 tous les utilisateurs du syst\u00E8me. S'il vous pla\u00EEt lisez l'aide contextuelle pour plus d'informations.
core.webdav=WebDAV
webdav.digest=Utilise l'authentification Digest pour l'acc\u00E8s HTTP
webdav.for.learners.bookmarks=Acc\u00E8s aux favoris pour les \u00E9tudiants
webdav.for.learners.participants=Acc\u00E8s aux cours pour les \u00E9tudiants
webdav.link=Montre les liens WebDAV
webdav.module=Acc\u00E8s WebDAV
webdav.on=on
webdav.prepend.reference=Ajouter la r\u00E9f\u00E9rence au nom du cours
webdav.termsfolders=Grouper les cours par semestre
......@@ -159,7 +159,8 @@ public class URLBuilder {
buildURI(sb, ajaxEnabled? AJAXFlags.MODE_TOBGIFRAME : AJAXFlags.MODE_NORMAL, commands);
sb.append("\" onclick=\"");
if(ajaxEnabled) {
buildXHREvent(sb, urlEnding, dirtyCheck, pushState, commands).append(" return false;");
String escapedUrlEnding = StringHelper.escapeJavaScript(urlEnding);
buildXHREvent(sb, escapedUrlEnding, dirtyCheck, pushState, commands).append(" return false;");
} else if(dirtyCheck) {
sb.append("return o2cl();");
}
......
#Mon Oct 22 16:27:04 CEST 2012
#Wed Feb 17 16:54:36 CET 2016
chooseFolder=Choisir le dossier
condition.accessDownloaders.title=Lecture seule (download)
condition.accessUploaders.title=Ecriture (upload)
createButton=Cr\u00E9er le dossier
createFolder=Cr\u00E9er le dossier de stockage
createPath=Chemin cr\u00E9\u00E9
error.missingfolder.long=Vous devez configurer un dossier.
error.missingfolder.short=Vous devez configurer un dossier.
folder.view=Ouvrir dossier
info.folder=T\u00E9l\u00E9charger fichiers
info.quota=Adapter le quota de ce dossier
info.select=Choisir un dossier
info.sharedfolder=Pour les dossiers de ressources, les membres du cours n'ont qu'un acc\u00E8s en lecture (download), les t\u00E9l\u00E9versements ne sont pas autoris\u00E9s.
noFolder=Le dossier configur\u00E9 n'est plus disponible. Contactez s'il vous pla\u00EEt l'administrateur du cours.
pane.tab.accessibility=Acc\u00E8s
pane.tab.folder=Configuration
pathChoose=Destination du fichier
pathChoose.auto=Dossier g\u00E9n\u00E9r\u00E9 automatiquement
pathChoose.custom=Choisir un dossier dans le dossier de stockage du cours
peekview.allItemsLink=Tous les documents
preview.canDownload=Download permis
preview.canUpload=Upload permis
......@@ -23,5 +26,8 @@ preview.downloadfile=T\u00E9l\u00E9charger le fichier
preview.header=Configuration du dossier pour l'utilisateur simul\u00E9
preview.info=Le contenu du fichier est repr\u00E9sent\u00E9 ci-dessous (l'aper\u00E7u uniquement possible en lecture\!)
preview.quotaKB=Quota en KB
subPathLab.dummy=Aucun dossier de stockage n'est configur\u00E9 pour l'instant.
subPathLab.label=Chemin du fichier
title_bc=Dossier
warn.folderdelete=Attention\: Tous les fichiers dans le dossier vont \u00EAtre effac\u00E9s.
warning.no.sharedfolder=Le dossier de ressource configur\u00E9 n'est plus disponible.
......@@ -49,6 +49,11 @@ public class MonitoringWebService {
public MonitoringWebService() {
//make Spring happy
}
@Path("status")
public StatusWebservice getStatus() {
return new StatusWebservice();
}
@Path("runtime")
public RuntimeWebService getCompilationXml() {
......
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.restapi.system;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.olat.admin.sysinfo.manager.SessionStatsManager;
import org.olat.core.CoreSpringFactory;
import org.olat.core.commons.persistence.DBFactory;
import org.olat.core.id.Identity;
import org.olat.core.id.OLATResourceable;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.core.util.CodeHelper;
import org.olat.core.util.FileUtils;
import org.olat.core.util.SessionInfo;
import org.olat.core.util.UserSession;
import org.olat.core.util.WebappHelper;
import org.olat.core.util.WorkThreadInformations;
import org.olat.core.util.resource.OresHelper;
import org.olat.core.util.session.UserSessionManager;
import org.olat.group.BusinessGroup;
import org.olat.properties.Property;
import org.olat.properties.PropertyManager;
import org.olat.restapi.system.vo.StatusVO;
/**
*
* Initial date: 15.02.2016<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class StatusWebservice {
private static final OLog log = Tracing.createLoggerFor(StatusWebservice.class);
private static final String PING_REF = "REST-Ping";
private static final OLATResourceable PING_RESOURCE = OresHelper.createOLATResourceableInstance(PING_REF, 42l);
/**
* Return the statistics about runtime: uptime, classes loaded, memory
* summary, threads count...
*
* @response.representation.200.qname {http://www.example.com}runtimeVO
* @response.representation.200.mediaType application/xml, application/json
* @response.representation.200.doc The version of the instance
* @response.representation.200.example {@link org.olat.restapi.system.vo.Examples#SAMPLE_RUNTIMEVO}
* @response.representation.401.doc The roles of the authenticated user are not sufficient
* @param request The HTTP request
* @return The informations about runtime, uptime, classes loaded, memory summary...
*/
@GET
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response getSystemSummaryVO() {
StatusVO stats = new StatusVO();
//File
try {
long startFile = System.nanoTime();
File infoFile = setInfoFiles("ping");
WorkThreadInformations.unset();
stats.setWriteFileInMilliseconds(CodeHelper.nanoToMilliTime(startFile));
stats.setWriteFile(infoFile.exists());
infoFile.delete();
} catch (Exception e) {
stats.setWriteFile(false);
stats.setWriteFileInMilliseconds(-1l);
log.error("", e);
}
//Datebase
try {
stats.setWriteDb(true);
PropertyManager propertyManager = CoreSpringFactory.getImpl(PropertyManager.class);
List<Property> props = propertyManager.findProperties((Identity)null, (BusinessGroup)null, PING_RESOURCE, PING_REF, PING_REF);
if(props != null && props.size() > 0) {
for(Property prop:props) {
propertyManager.deleteProperty(prop);
}
DBFactory.getInstance().commit();
}
long startDB = System.nanoTime();
Property prop = propertyManager.createPropertyInstance(null, null, PING_RESOURCE, PING_REF, PING_REF, 0f, 0l, "-", "-");
DBFactory.getInstance().commit();
stats.setWriteDbInMilliseconds(CodeHelper.nanoToMilliTime(startDB));
propertyManager.deleteProperty(prop);
DBFactory.getInstance().commit();
} catch (Exception e) {
stats.setWriteDb(false);
stats.setWriteDbInMilliseconds(-1l);
log.error("", e);
}
//Secure authenticated user
UserSessionManager sessionManager = CoreSpringFactory.getImpl(UserSessionManager.class);
Set<UserSession> userSessions = sessionManager.getAuthenticatedUserSessions();
int secureAuthenticatedCount = 0;
for (UserSession usess:userSessions) {
SessionInfo sessInfo = usess.getSessionInfo();
if (sessInfo.isWebDAV() || sessInfo.isREST()) {
//
} else if (sessInfo.isSecure()) {
secureAuthenticatedCount++;
}
}
stats.setSecureAuthenticatedCount(secureAuthenticatedCount);
//Concurrent dispatch threads
SessionStatsManager sessionStatsManager = CoreSpringFactory.getImpl(SessionStatsManager.class);
stats.setConcurrentDispatchThreads(sessionStatsManager.getConcurrentCounter());
return Response.ok(stats).build();
}
/**
* The method return an exception if something happens.
*
* @param filePath
* @throws IOException
*/
public static File setInfoFiles(String filePath) throws IOException {
File file = new File(WebappHelper.getUserDataRoot(), "threadInfos");
if(!file.exists()) {
file.mkdirs();
}
File infoFile = new File(file, Thread.currentThread().getName());
FileUtils.save(new FileOutputStream(infoFile), filePath, "UTF-8");
return infoFile;
}
}
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.restapi.system.vo;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* Initial date: 15.02.2016<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "statusVO")
public class StatusVO {
@XmlAttribute(name="writeFile", required=true)
private boolean writeFile;
@XmlAttribute(name="writeFileInMilliseconds", required=true)
private long writeFileInMilliseconds;
@XmlAttribute(name="writeDb", required=true)
private boolean writeDb;
@XmlAttribute(name="writeDbInMilliseconds", required=true)
private long writeDbInMilliseconds;
@XmlAttribute(name="secureAuthenticatedCount", required=true)
private int secureAuthenticatedCount;
@XmlAttribute(name="concurrentDispatchThreads", required=true)
private long concurrentDispatchThreads;
public boolean isWriteFile() {
return writeFile;
}
public void setWriteFile(boolean writeFile) {
this.writeFile = writeFile;
}
public long getWriteFileInMilliseconds() {
return writeFileInMilliseconds;
}
public void setWriteFileInMilliseconds(long writeFileInMilliseconds) {
this.writeFileInMilliseconds = writeFileInMilliseconds;
}
public boolean isWriteDb() {
return writeDb;
}
public void setWriteDb(boolean writeDb) {
this.writeDb = writeDb;
}
public long getWriteDbInMilliseconds() {
return writeDbInMilliseconds;
}
public void setWriteDbInMilliseconds(long writeDbInMilliseconds) {
this.writeDbInMilliseconds = writeDbInMilliseconds;
}
public int getSecureAuthenticatedCount() {
return secureAuthenticatedCount;
}
public void setSecureAuthenticatedCount(int secureAuthenticatedCount) {
this.secureAuthenticatedCount = secureAuthenticatedCount;
}
public long getConcurrentDispatchThreads() {
return concurrentDispatchThreads;
}
public void setConcurrentDispatchThreads(long concurrentDispatchThreads) {
this.concurrentDispatchThreads = concurrentDispatchThreads;
}
}
......@@ -36,6 +36,7 @@ import org.olat.restapi.system.vo.MemoryStatisticsVO;
import org.olat.restapi.system.vo.MemoryVO;
import org.olat.restapi.system.vo.MonitoringInfosVO;
import org.olat.restapi.system.vo.OpenOLATStatisticsVO;
import org.olat.restapi.system.vo.StatusVO;
import org.olat.restapi.system.vo.ReleaseInfosVO;
import org.olat.restapi.system.vo.RepositoryStatisticsVO;
import org.olat.restapi.system.vo.RuntimeStatisticsVO;
......@@ -59,6 +60,21 @@ import org.olat.test.OlatJerseyTestCase;
*/
public class SystemTest extends OlatJerseyTestCase {
@Test
public void testMonitoringStatus() throws IOException, URISyntaxException {
RestConnection conn = new RestConnection();
assertTrue(conn.login("administrator", "openolat"));
URI systemUri = conn.getContextURI().path("system").path("monitoring").path("status").build();
StatusVO stats = conn.get(systemUri, StatusVO.class);
Assert.assertNotNull(stats);
Assert.assertTrue(stats.isWriteDb());
Assert.assertTrue(stats.isWriteFile());
Assert.assertTrue(stats.getConcurrentDispatchThreads() >= 0l);
Assert.assertTrue(stats.getSecureAuthenticatedCount() >= 0l);
conn.shutdown();
}
@Test
public void testRuntimeStatisticsInfos() throws IOException, URISyntaxException {
RestConnection conn = new RestConnection();
......
......@@ -802,11 +802,11 @@ public class CourseTest {
Assert.assertEquals(podcastTitle, podcastH2.getText().trim());
FeedPage feed = FeedPage.getFeedPage(browser);
feed.newExternalPodcast("http://pod.drs.ch/rock_special_mpx.xml");
feed.newExternalPodcast("http://podcasts.srf.ch/rock_special_mpx.xml");
//check only that the "episodes" title is visible
By episodeTitleby = By.cssSelector("div.o_podcast_episodes>h4.o_title");
OOGraphene.waitElement(episodeTitleby, 5, browser);
OOGraphene.waitElement(episodeTitleby, 20, browser);
WebElement episodeH4 = browser.findElement(episodeTitleby);
Assert.assertNotNull(episodeH4);
}
......@@ -859,7 +859,7 @@ public class CourseTest {
//check only that the subscription link is visible
By subscriptionBy = By.cssSelector("div.o_subscription>a");
OOGraphene.waitElement(subscriptionBy, 10, browser);
OOGraphene.waitElement(subscriptionBy, 20, browser);
WebElement subscriptionLink = browser.findElement(subscriptionBy);
Assert.assertTrue(subscriptionLink.isDisplayed());
}
......
......@@ -38,8 +38,6 @@ import org.openqa.selenium.WebElement;
*/
public class BookingPage {
private static final By tokenIconBy = By.className("o_ac_token_icon");
private static final By addMethodLinksBy = By.cssSelector("fieldset.o_ac_configuration ul.dropdown-menu a");
private WebDriver browser;
......@@ -64,20 +62,19 @@ public class BookingPage {
* @return This page
*/
public BookingPage addTokenMethod() {
return addMethod(tokenIconBy);
addMethod("o_ac_token_icon");
By popupBy = By.cssSelector("div.modal-dialog");
OOGraphene.waitElement(popupBy, 5, browser);
return this;
}
private BookingPage addMethod(By iconBy) {
List<WebElement> links = browser.findElements(addMethodLinksBy);
WebElement tokenLink = null;
for(WebElement link:links) {
List<WebElement> icons = link.findElements(iconBy);
if(icons.size() > 0) {
tokenLink = link;
}
}
Assert.assertNotNull(tokenLink);
tokenLink.click();
private BookingPage addMethod(String iconClassname) {
//wait menu
By addMenuBy = By.cssSelector("fieldset.o_ac_configuration ul.dropdown-menu");
OOGraphene.waitElement(addMenuBy, 5, browser);
By addMethodBy = By.xpath("//fieldset[contains(@class,'o_ac_configuration')]//ul[contains(@class,'dropdown-menu')]//a[//i[contains(@class,'" + iconClassname + "')]]");
WebElement methodLink = browser.findElement(addMethodBy);
methodLink.click();
OOGraphene.waitBusy(browser);
return this;
}
......
......@@ -107,6 +107,8 @@ public class CourseEditorPageFragment {
By rootNodeBy = By.cssSelector("span.o_tree_link.o_tree_l0>a");
browser.findElement(rootNodeBy).click();
OOGraphene.waitBusy(browser);
By rootNodeActiveBy = By.cssSelector("span.o_tree_link.o_tree_l0.active");
OOGraphene.waitElement(rootNodeActiveBy, 5, browser);
return this;
}
......@@ -149,6 +151,10 @@ public class CourseEditorPageFragment {
}
private CourseEditorPageFragment selectTab(By tabBy) {
//make sure the tab bar is loaded
By navBarBy = By.cssSelector("ul.o_node_config");
OOGraphene.waitElement(navBarBy, 5, browser);
List<WebElement> tabLinks = browser.findElements(navBarNodeConfiguration);
boolean found = false;
......
......@@ -53,6 +53,11 @@ public class OOGraphene {
Graphene.waitModel(browser).pollingEvery(poolingDuration, TimeUnit.MILLISECONDS).until(new BusyPredicate());
}
public static void waitBusy(WebDriver browser, int timeoutInSeconds) {
Graphene.waitModel(browser).withTimeout(timeoutInSeconds, TimeUnit.SECONDS)
.pollingEvery(poolingDuration, TimeUnit.MILLISECONDS).until(new BusyPredicate());
}
public static void waitElement(By element, WebDriver browser) {
Graphene.waitModel(browser).pollingEvery(poolingDuration, TimeUnit.MILLISECONDS).until().element(element).is().visible();
}
......
......@@ -110,7 +110,7 @@ public class FeedPage {
//save the settings
By saveButton = By.xpath("//div[contains(@class,'modal-body')]//form//button[contains(@class,'btn-primary')]");
browser.findElement(saveButton).click();
OOGraphene.waitBusy(browser);
OOGraphene.waitBusy(browser, 20);
return this;
}
......
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