diff --git a/CourseEditorOperations.php b/CourseEditorOperations.php
index 10cf8cb..141c078 100644
--- a/CourseEditorOperations.php
+++ b/CourseEditorOperations.php
@@ -1,314 +1,313 @@
type) {
case 'fromTopic':
- self::createNewCourseFromTopic($operation->params);
+ $result = self::createNewCourseFromTopic($operation);
+ CourseEditorUtils::setComposedOperationSuccess($operation, $result);
break;
case 'fromDepartment':
- self::createNewCourseFromDepartment($operation->params);
+ $result = self::createNewCourseFromDepartment($operation);
+ CourseEditorUtils::setComposedOperationSuccess($operation, $result);
break;
}
- //FIXME Must be a serius return object and error handling
- return "ok";
+ return json_encode($operation);
}
public static function manageCourseMetadataOp($operationRequested){
$operation = json_decode($operationRequested);
$params = $operation->params;
$title = $params[0];
$topic = $params[1];
$description = $params[2];
$externalReferences = $params[3];
$isImported = $params[4];
$originalAuthors = $params[5];
$isReviewed = $params[6];
$reviewedOn = $params[7];
$pageTitle = MWNamespace::getCanonicalName(NS_COURSEMETADATA) . ':' . $title;
$metadata = "" . $topic . "\r\n";
if($description !== '' && $description !== null){
$metadata .= "" . $description . "\r\n";
}
if($externalReferences !== '' && $externalReferences !== null){
$metadata .= "" . $externalReferences . "\r\n";
}
if($isImported !== false || $isReviewed !== false){
$metadata .= "" . true . "\r\n";
if($isImported !== false){
$metadata .= "" . $isImported . "\r\n";
$metadata .= "" . $originalAuthors . "\r\n";
}
if($isReviewed !== false){
$metadata .= "" . $isReviewed . "\r\n";
$metadata .= "" . $reviewedOn . "\r\n";
}
}
$resultCreateMetadataPage = CourseEditorUtils::editWrapper($pageTitle, $metadata , null, null);
CourseEditorUtils::setSingleOperationSuccess($operation, $resultCreateMetadataPage);
return json_encode($operation);
- //FIXME Return an object with results in order to display error to the user
}
private function createBasicCourseMetadata($topic, $title, $description){
$topic = ($topic === null ? $title : $topic);
$pageTitle = MWNamespace::getCanonicalName(NS_COURSEMETADATA) . ':' . $title;
$metadata = "" . $topic . "\r\n";
if($description !== '' && $description !== null){
$metadata .= "" . $description . "\r\n";
}
- $resultCreateMetadataPage = CourseEditorUtils::editWrapper($pageTitle, $metadata , null, null);
- //FIXME Return an object with results in order to display error to the user
+ $apiResult = CourseEditorUtils::editWrapper($pageTitle, $metadata , null, null);
+ return $apiResult;
}
- private function createNewCourseFromDepartment($params){
+ private function createNewCourseFromDepartment(&$operation){
+ $params = $operation->params;
$department = $params[0];
$title = $params[1];
$description = $params[2];
$namespace = $params[3];
if($department != null && $title != null && $namespace != null){
$compareResult = strcmp($namespace, 'NS_COURSE');
$namespaceCostant = ($compareResult == 0 ? NS_COURSE : NS_USER);
$pageTitle = MWNamespace::getCanonicalName($namespaceCostant) . ':';
if($namespaceCostant == NS_USER){
- self::createPrivateCourse($pageTitle, null, $title, $description);
+ $result = self::createPrivateCourse($pageTitle, $topic, $title, $description);
+ $user = CourseEditorUtils::getRequestContext()->getUser();
+ $userPage = $pageTitle . $user->getName();
+ $operation->courseTitle = $userPage . '/' . $title;
}else{
- self::createPublicCourseFromDepartment($pageTitle, $department, $title, $description);
+ $result = self::createPublicCourseFromDepartment($pageTitle, $department, $title, $description);
+ $operation->courseTitle = $pageTitle . $title;
}
}
+
+ return $result;
}
- private function createNewCourseFromTopic($params){
+ private function createNewCourseFromTopic(&$operation){
+ $params = $operation->params;
$topic = $params[0];
$title = $params[1];
$description = $params[2];
$namespace = $params[3];
if($topic != null && $title != null && $namespace != null){
$compareResult = strcmp($namespace, 'NS_COURSE');
$namespaceCostant = ($compareResult === 0 ? NS_COURSE : NS_USER);
$pageTitle = MWNamespace::getCanonicalName($namespaceCostant) . ':';
if($namespaceCostant == NS_USER){
- self::createPrivateCourse($pageTitle, $topic, $title, $description);
+ $result = self::createPrivateCourse($pageTitle, $topic, $title, $description);
+ $user = CourseEditorUtils::getRequestContext()->getUser();
+ $userPage = $pageTitle . $user->getName();
+ $operation->courseTitle = $userPage . '/' . $title;
}else{
- self::createPublicCourseFromTopic($pageTitle, $topic, $title, $description);
+ $result = self::createPublicCourseFromTopic($pageTitle, $topic, $title, $description);
+ $operation->courseTitle = $pageTitle . $title;
}
}
+ return $result;
}
private function createPrivateCourse($pageTitle, $topic, $title, $description){
$context = CourseEditorUtils::getRequestContext();
$user = $context->getUser();
$userPage = $pageTitle . $user->getName();
$titleWithUser = $user->getName() . '/' . $title;
$pageTitle = $userPage . "/" . $title;
$resultCreateCourse = CourseEditorUtils::editWrapper($pageTitle, "{{CCourse|}}", null, null);
$resultCreateMetadataPage = self::createBasicCourseMetadata($topic, $titleWithUser, $description);
$textToPrepend = "{{Course|" . $title . "|" . $user->getName() . "}}";
$resultPrependToUserPage = CourseEditorUtils::editWrapper($userPage, null, $textToPrepend, null);
- //FIXME Return an object with results in order to display error to the user
+ return array($resultCreateCourse, $resultCreateMetadataPage, $resultPrependToUserPage);
+
}
private function createPublicCourseFromTopic($pageTitle, $topic, $title, $description){
$pageTitle .= $title;
$resultCreateCourse = CourseEditorUtils::editWrapper($pageTitle, "{{CCourse|}}", null, null);
$topicCourses = CourseEditorUtils::getTopicCourses($topic);
$text = $topicCourses . "{{Course|" . $title . "}}}}";
$resultCreateMetadataPage = self::createBasicCourseMetadata($topic, $title, $description);
$resultAppendToTopic = CourseEditorUtils::editWrapper($topic, $text, null, null);
- //FIXME Return an object with results in order to display error to the user
-
+ return array($resultCreateCourse, $resultCreateMetadataPage, $resultAppendToTopic);
}
private function createPublicCourseFromDepartment($pageTitle, $department, $title, $description){
$pageTitle .= $title;
$resultCreateCourse = CourseEditorUtils::editWrapper($pageTitle, "{{CCourse|}}", null, null);
$text = "{{Topic|" . "{{Course|" . $title . "}}}}";
$listElementText = "\r\n* [[" . $title . "]]";
$resultCreateMetadataPage = self::createBasicCourseMetadata(null, $title, $description);
$resultAppendToTopic = CourseEditorUtils::editWrapper($title, $text, null, null);
$resultAppendToDepartment = CourseEditorUtils::editWrapper($department, null, null, $listElementText);
- //FIXME Return an object with results in order to display error to the user
-
+ return array($resultCreateCourse, $resultCreateMetadataPage, $resultAppendToTopic, $resultAppendToDepartment);
}
public static function applyCourseOp($courseName, $operation){
$value = json_decode($operation);
switch ($value->action) {
case 'rename-move-task':
$sectionName = $value->elementName;
$newSectionName = $value->newElementName;
- /*$chapters = CourseEditorUtils::getChapters($courseName . '/' .$sectionName);
- $newSectionText = "";
- foreach ($chapters as $chapter) {
- $newSectionText .= "* [[" . $courseName . "/" . $newSectionName . "/" . $chapter ."|". $chapter ."]]\r\n";
- }*/
$pageTitle = $courseName . "/" . $sectionName;
$newPageTitle = $courseName . '/' . $newSectionName;
$apiResult = CourseEditorUtils::moveWrapper($pageTitle, $newPageTitle);
- //$resultEdit = CourseEditorUtils::editWrapper($newPageTitle, $newSectionText, null, null);
- //$apiResult = array($resultMove, $resultEdit);
CourseEditorUtils::setSingleOperationSuccess($value, $apiResult);
break;
case 'rename-update-task':
$sectionName = $value->elementName;
$newSectionName = $value->newElementName;
$chapters = CourseEditorUtils::getChapters($courseName . '/' .$newSectionName);
$newSectionText = "";
foreach ($chapters as $chapter) {
$newSectionText .= "* [[" . $courseName . "/" . $newSectionName . "/" . $chapter ."|". $chapter ."]]\r\n";
}
- //$pageTitle = $courseName . "/" . $sectionName;
$newPageTitle = $courseName . '/' . $newSectionName;
- //$apiResult = CourseEditorUtils::moveWrapper($pageTitle, $newPageTitle);
$apiResult = CourseEditorUtils::editWrapper($newPageTitle, $newSectionText, null, null);
- //$apiResult = array($resultMove, $resultEdit);
CourseEditorUtils::setSingleOperationSuccess($value, $apiResult);
break;
case 'delete-chapters-task':
$user = CourseEditorUtils::getRequestContext()->getUser();
$sectionName = $value->elementName;
$chapters = CourseEditorUtils::getChapters($courseName . '/' . $sectionName);
$title = Title::newFromText( $courseName . '/' . $sectionName, $defaultNamespace=NS_MAIN );
$pageTitle = $courseName . '/' . $sectionName;
if(!$title->userCan('delete', $user, 'secure')){
$prependText = "\r\n{{DeleteMe}}";
- //$resultSection = CourseEditorUtils::editWrapper($pageTitle, null, $prependText, null);
foreach ($chapters as $chapter) {
$pageTitle = $courseName . '/' . $sectionName . '/' . $chapter;
$prependText = "\r\n{{DeleteMe}}";
$apiResult = CourseEditorUtils::editWrapper($pageTitle, null, $prependText, null);
}
}else {
foreach ($chapters as $chapter) {
$pageTitle = $courseName . '/' . $sectionName . '/' . $chapter;
- $resultChapters = CourseEditorUtils::deleteWrapper($pageTitle);
+ $apiResult = CourseEditorUtils::deleteWrapper($pageTitle);
}
- //$resultSection = CourseEditorUtils::deleteWrapper($pageTitle);
}
- //$apiResult = array($resultSection, $resultChapters);
CourseEditorUtils::setSingleOperationSuccess($value, $apiResult);
break;
case 'delete-section-task':
$user = CourseEditorUtils::getRequestContext()->getUser();
$sectionName = $value->elementName;
$title = Title::newFromText( $courseName . '/' . $sectionName, $defaultNamespace=NS_MAIN );
$pageTitle = $courseName . '/' . $sectionName;
if(!$title->userCan('delete', $user, 'secure')){
$prependText = "\r\n{{DeleteMe}}";
$apiResult = CourseEditorUtils::editWrapper($pageTitle, null, $prependText, null);
}else {
$apiResult = CourseEditorUtils::deleteWrapper($pageTitle);
}
CourseEditorUtils::setSingleOperationSuccess($value, $apiResult);
break;
case 'add':
$sectionName = $value->elementName;
$pageTitle = $courseName . '/' . $sectionName;
$text = "";
$apiResult = CourseEditorUtils::editWrapper($pageTitle, $text, null, null);
CourseEditorUtils::setSingleOperationSuccess($value, $apiResult);
break;
case 'update':
$newCourseText = "{{CCourse|\r\n";
$newSectionsArray = json_decode($value->elementsList);
foreach ($newSectionsArray as $section) {
$newCourseText .= "{{SSection|" . $section ."}}\r\n";
}
$newCourseText .= "}}";
$categories = CourseEditorUtils::getCategories($courseName);
if(sizeof($categories) > 0){
foreach ($categories as $category) {
$newCourseText .= "\r\n[[" . $category['title'] . "]]";
}
}
$apiResult = CourseEditorUtils::editWrapper($courseName, $newCourseText, null, null);
CourseEditorUtils::setSingleOperationSuccess($value, $apiResult);
break;
case 'update-collection':
$apiResult = CourseEditorUtils::updateCollection($courseName);
CourseEditorUtils::setSingleOperationSuccess($value, $apiResult);
break;
/*case 'fix-link':
$targetPage = $value->elementName;
$linkToReplace = $value->linkToReplace;
list($course, $section, $chapter) = explode('/', $linkToReplace);
$replacement = $course . '/' . $value->replacement . '/' . $chapter;
$title = Title::newFromText($targetPage);
$page = WikiPage::factory( $title );
$content = $page->getContent( Revision::RAW );
$text = ContentHandler::getContentText( $content );
$newText = str_replace(str_replace(' ', '_', $linkToReplace), $replacement, $text);
$apiResult = CourseEditorUtils::editWrapper($targetPage, $newText, null, null);
CourseEditorUtils::setSingleOperationSuccess($value, $apiResult);
$value->text = $newText;
break;*/
}
return json_encode($value);
}
public static function applySectionOp($sectionName, $operation){
$context = CourseEditorUtils::getRequestContext();
$value = json_decode($operation);
switch ($value->action) {
case 'rename':
$chapterName = $value->elementName;
$newChapterName = $value->newElementName;
$from = $sectionName . '/' . $chapterName;
$to = $sectionName . '/' . $newChapterName;
$apiResult = CourseEditorUtils::moveWrapper($from, $to);
CourseEditorUtils::setSingleOperationSuccess($value, $apiResult);
break;
case 'delete':
$user = $context->getUser();
$chapterName = $value->elementName;
$title = Title::newFromText($sectionName . '/' . $chapterName, $defaultNamespace=NS_MAIN);
if(!$title->userCan('delete', $user, 'secure')){
$pageTitle = $sectionName . '/' . $chapterName;
$prependText = "\r\n{{DeleteMe}}";
$apiResult = CourseEditorUtils::editWrapper($pageTitle, null, $prependText, null);
}else {
$pageTitle = $sectionName . '/' . $chapterName;
$apiResult = CourseEditorUtils::deleteWrapper($pageTitle);
}
CourseEditorUtils::setSingleOperationSuccess($value, $apiResult);
break;
case 'add':
$chapterName = $value->elementName;
$pageTitle = $sectionName . '/' . $chapterName;
$text = "";
$apiResult = CourseEditorUtils::editWrapper($pageTitle, $text, null, null);
CourseEditorUtils::setSingleOperationSuccess($value, $apiResult);
break;
case 'update':
$newSectionText = "";
$newChaptersArray = json_decode($value->elementsList);
foreach ($newChaptersArray as $chapter) {
$newSectionText .= "* [[" . $sectionName . "/" . $chapter ."|". $chapter ."]]\r\n";
}
$apiResult = CourseEditorUtils::editWrapper($sectionName, $newSectionText);
CourseEditorUtils::setSingleOperationSuccess($value, $apiResult);
break;
case 'purge':
$explodedString = explode("/", $sectionName);
$pageToBePurged = (sizeof($explodedString) > 2 ? $explodedString[0] . "/" . $explodedString[1] : $explodedString[0]);
$apiResult = CourseEditorUtils::purgeWrapper($pageToBePurged);
CourseEditorUtils::setSingleOperationSuccess($value, $apiResult);
break;
case 'update-collection':
$explodedString = explode("/", $sectionName);
$courseName = (sizeof($explodedString) > 2 ? $explodedString[0] . "/" . $explodedString[1] : $explodedString[0]);
$apiResult = CourseEditorUtils::updateCollection($courseName);
CourseEditorUtils::setSingleOperationSuccess($value, $apiResult);
break;
}
return json_encode($value);
}
}
diff --git a/CourseEditorTemplates.php b/CourseEditorTemplates.php
index f4f013d..f1edc7a 100644
--- a/CourseEditorTemplates.php
+++ b/CourseEditorTemplates.php
@@ -1,217 +1,220 @@
data['section'];
?>
+
+
+
+
data['course'];
?>
+
+
+
+
data['course'];
if($this->data['metadataResult']){
$metadataResult = $this->data['metadataResult'];
}
?>
getNamespace();
if(MWNamespace::equals($namespaceIndex, NS_USER)){
self::updateUserCollection($courseName);
}else {
$pageTitle = "Project:" . wfMessage('courseeditor-collection-book-category') ."/" . $name;
$collectionText = "{{" . wfMessage('courseeditor-collection-savedbook-template') . "
\n| setting-papersize = a4
\n| setting-toc = auto
\n| setting-columns = 1
\n| setting-footer = yes\n}}\n";
$collectionText .= "== " . str_replace('_', ' ', $name) . " ==\r\n";
$sections = self::getSections($courseName);
foreach ($sections as $section) {
$chapters = self::getChapters($courseName . '/' .$section);
$collectionText .= ";" . $section . "\r\n";
foreach ($chapters as $chapter) {
$collectionText .= ":[[" . $courseName . "/" . $section . "/" . $chapter . "]]\r\n";
}
}
$categoryName = wfMessage('courseeditor-collection-book-category');
if ( !$categoryName->isDisabled() ) {
$catTitle = Title::makeTitle( NS_CATEGORY, $categoryName );
if ( !is_null( $catTitle ) ) {
$collectionText .= "\n[[" . $catTitle->getPrefixedText() ."|" . $name . "]]";
}
}
$editResult = self::editWrapper($pageTitle, $collectionText, null, null);
return $editResult;
}
}
private function updateUserCollection($courseName){
list($namespaceAndUser, $title) = explode('/', $courseName, 2);
$pageTitle = $namespaceAndUser . "/" . wfMessage('courseeditor-collection-book-category') . "/" . $title;
$collectionText = "{{" . wfMessage('courseeditor-collection-savedbook-template') . "
\n| setting-papersize = a4
\n| setting-toc = auto
\n| setting-columns = 1
\n| setting-footer = yes\n}}\n";
$collectionText .= "== " . str_replace('_', ' ', $title). " ==\r\n";
$sections = self::getSections($courseName);
foreach ($sections as $section) {
$chapters = self::getChapters($courseName . '/' .$section);
$collectionText .= ";" . $section . "\r\n";
foreach ($chapters as $chapter) {
$collectionText .= ":[[" . $courseName . "/" . $section . "/" . $chapter . "]]\r\n";
}
}
$categoryName = wfMessage('courseeditor-collection-book-category');
if ( !$categoryName->isDisabled() ) {
$catTitle = Title::makeTitle( NS_CATEGORY, $categoryName );
if ( !is_null( $catTitle ) ) {
$collectionText .= "\n[[" . $catTitle->getPrefixedText() ."|" . $title. "]]";
}
}
$editResult = self::editWrapper($pageTitle, $collectionText, null, null);
return $editResult;
}
public static function getMetadata($courseName){
$title = Title::newFromText($courseName, $defaultNamespace=NS_COURSEMETADATA );
$page = WikiPage::factory( $title );
$content = $page->getContent( Revision::RAW );
$text = ContentHandler::getContentText( $content );
if($text === ''){
return null;
}
$regex = "/(.*?)/s";
preg_match_all($regex, $text, $matches, PREG_PATTERN_ORDER);
$metadataResult = array();
$metadataKeys = $matches[1];
$metadataValues = $matches[2];
for ($i=0; $i < sizeof($metadataKeys); $i++) {
$metadataResult[$metadataKeys[$i]] = $metadataValues[$i];
}
return $metadataResult;
}
public static function getTopicCourses($topic){
$title = Title::newFromText($topic, $defaultNamespace=NS_MAIN );
$page = WikiPage::factory( $title );
$content = $page->getContent( Revision::RAW );
$text = ContentHandler::getContentText( $content );
$textNoNewLines = trim(preg_replace('/\n+/', '', $text));
$regex = "/({{Topic|.+)}}.*$/";
preg_match_all($regex, $textNoNewLines, $matches, PREG_PATTERN_ORDER);
return $matches[1][0];
}
/**
* This method is a workaround (read it HACK) to check the API results.
* MediaWiki ApiResult object is not "standard" but if an error/exception
* occurs the result variable is a string.
*/
public static function setSingleOperationSuccess(&$operation, $result){
$isSuccess = true;
if (is_string($result)) {
$isSuccess = false;
}
$operation->success = $isSuccess;
}
/**
* This method is a workaround (read it HACK) to check the API results.
* MediaWiki ApiResult object is not "standard" but if an error/exception
* occurs the result variable is a string.
*/
- public static function setComposedOperationSuccess(&$operation, $result){
+ public static function setComposedOperationSuccess(&$operation, $resultsArray){
$isSuccess = true;
- if (is_string($result[0]) || is_string($result[1])) {
- $isSuccess = false;
+ foreach ($resultsArray as $result) {
+ if (is_string($result)) {
+ $isSuccess = false;
+ break;
+ }
}
$operation->success = $isSuccess;
}
public static function getRequestContext(){
if(self::$requestContext == null)
{
$context = new RequestContext();
self::$requestContext = $context;
}
return self::$requestContext;
}
public static function getCategories($courseName){
try {
$api = new ApiMain(
new DerivativeRequest(
self::getRequestContext()->getRequest(),
array(
'action' => 'query',
'titles' => $courseName,
'prop' => 'categories'
)
),
true
);
$api->execute();
$results = $api->getResult()->getResultData(null, array('Strip' => 'all'));
$page = reset($results['query']['pages']);
return $page['categories'];
} catch(UsageException $e){
return $e->getMessage();
}
}
public static function getChapters($sectionName){
$title = Title::newFromText($sectionName, $defaultNamespace=NS_MAIN );
$page = WikiPage::factory( $title );
$content = $page->getContent( Revision::RAW );
$text = ContentHandler::getContentText( $content );
$regex = "/\*\s*\[{2}([^|]*)\|?([^\]]*)\]{2}\s*/";
preg_match_all($regex, $text, $matches, PREG_PATTERN_ORDER);
return $matches[2];
}
public static function getSections($courseName){
$title = Title::newFromText( $courseName, $defaultNamespace=NS_MAIN );
$page = WikiPage::factory( $title );
$content = $page->getContent( Revision::RAW );
$text = ContentHandler::getContentText( $content );
$regex = "/\{{2}SSection\|(.*)\}{2}/";
preg_match_all($regex, $text, $matches, PREG_PATTERN_ORDER);
return $matches[1];
}
public static function deleteWrapper($title){
$context = self::getRequestContext();
try {
$user = $context->getUser();
$token = $user->getEditToken();
$api = new ApiMain(
new DerivativeRequest(
$context->getRequest(),
array(
'action' => 'delete',
'title' => $title,
'token' => $token
),
true
),
true
);
$api->execute();
return $api->getResult()->getResultData(null, array('Strip' => 'all'));
} catch(UsageException $e){
return $e->getMessage();
}
}
public static function purgeWrapper($titles){
$context = self::getRequestContext();
try {
$api = new ApiMain(
new DerivativeRequest(
$context->getRequest(),
array(
'action' => 'purge',
'titles' => $titles,
'forcerecursivelinkupdate' => true
),
true
),
true
);
$api->execute();
return $api->getResult()->getResultData(null, array('Strip' => 'all'));
} catch(UsageException $e){
return $e->getMessage();
}
}
public static function editWrapper($title, $text, $textToPrepend, $textToAppend){
$context = self::getRequestContext();
try {
$user = $context->getUser();
$token = $user->getEditToken();
//$token = $this->getCsrfToken();
$api = new ApiMain(
new DerivativeRequest(
$context->getRequest(),
array(
'action' => 'edit',
'title' => $title,
'text' => $text,
// automatically override text
'prependtext' => $textToPrepend,
// automatically override text
'appendtext' => $textToAppend,
'notminor' => true,
'token' => $token
),
true
),
true
);
$api->execute();
return $api->getResult()->getResultData(null, array('Strip' => 'all'));
} catch(UsageException $e){
return $e->getMessage();
}
}
public static function moveWrapper($from, $to){
$context = self::getRequestContext();
try {
$user = $context->getUser();
$token = $user->getEditToken();
$api = new ApiMain(
new DerivativeRequest(
$context->getRequest(),
array(
'action' => 'move',
'from' => $from,
'to' => $to,
//'noredirect' => true,
'movetalk' => true,
'movesubpages' => true,
'token' => $token
),
true
),
true
);
$api->execute();
return $api->getResult()->getResultData(null, array('Strip' => 'all'));
} catch(UsageException $e){
return $e->getMessage();
}
}
public static function getBacklinksWrapper($title){
}
}
diff --git a/extension.json b/extension.json
index 942b1b7..913dca9 100644
--- a/extension.json
+++ b/extension.json
@@ -1,142 +1,144 @@
{
"name":"CourseEditor",
"version":"0.1.0",
"author":[
"Alessandro Tundo",
"Gianluca Rigoletti",
"Riccardo Iaconelli"
],
"url":"https://github.com/WikiToLearn/CourseEditor",
"descriptionmsg":"",
"license-name":"GPLv3",
"type":"special",
"AutoloadClasses":{
"CourseEditor":"CourseEditor.php",
"CourseEditorOperations":"CourseEditorOperations.php",
"CourseEditorUtils":"CourseEditorUtils.php",
"SectionEditorTemplate":"CourseEditorTemplates.php",
"CourseEditorTemplate" : "CourseEditorTemplates.php",
"CourseCreatorTemplate" : "CourseEditorTemplates.php",
"ManageMetadataTemplate" : "CourseEditorTemplates.php",
"SpecialCourseEditor":"SpecialCourseEditor.php"
},
"MessagesDirs":{
"CourseEditor":[
"i18n"
]
},
"ExtensionMessagesFiles": {
"CourseEditorAlias": "CourseEditor.alias.php",
"CourseEditorNamespaces": "CourseEditor.namespaces.php"
},
"ResourceFileModulePaths": {
"localBasePath": ""
},
"ResourceModules": {
"ext.courseEditor.manageMetadata": {
"scripts":["modules/manageMetadata.js"]
},
"ext.courseEditor.create": {
"scripts":["modules/createCourse.js"]
},
"ext.courseEditor.section": {
"scripts":[
"modules/commonFunctions.js",
"modules/sectionEditor.js"
],
"dependencies": [
"oojs-ui",
"mediawiki.util"
],
"styles": [
"modules/styles/style.css"
],
"messages": [
"courseeditor",
"courseeditor-add-new-chapter",
"courseeditor-save-section",
"courseeditor-cancel",
"courseeditor-rename",
"courseeditor-edit-dialog",
"courseeditor-message-dialog-title",
"courseeditor-message-dialog-message",
"courseeditor-message-dialog-cancel",
"courseeditor-message-dialog-restore",
"courseeditor-message-dialog-create-new",
"courseeditor-error-operation",
"courseeditor-operation-action-add",
"courseeditor-operation-action-delete",
"courseeditor-operation-action-rename",
"courseeditor-operation-action-purge",
"courseeditor-operation-action-update",
"courseeditor-operation-action-update-collection",
"courseeditor-error-operation-fail"
]
},
"ext.courseEditor.course": {
"scripts":[
"modules/commonFunctions.js",
"modules/courseEditor.js"
],
"dependencies": [
"oojs-ui",
"mediawiki.util"
],
"styles": [
"modules/styles/style.css"
],
"messages": [
"courseeditor",
"courseeditor-add-new-section",
"courseeditor-save-course",
"courseeditor-cancel",
"courseeditor-rename",
"courseeditor-edit-dialog",
"courseeditor-message-dialog-title",
"courseeditor-message-dialog-message",
"courseeditor-message-dialog-cancel",
"courseeditor-message-dialog-restore",
"courseeditor-message-dialog-create-new",
"courseeditor-error-operation",
"courseeditor-operation-action-add",
- "courseeditor-operation-action-delete",
- "courseeditor-operation-action-rename",
+ "courseeditor-operation-action-delete-chapters-task",
+ "courseeditor-operation-action-delete-section-task",
+ "courseeditor-operation-action-rename-move-task",
+ "courseeditor-operation-action-rename-update-task",
"courseeditor-operation-action-purge",
"courseeditor-operation-action-update",
"courseeditor-operation-action-update-collection",
"courseeditor-error-operation-fail"
]
}
},
"namespaces": [
{
"id": 2800,
"constant": "NS_COURSE",
"name": "Course",
"subpages" : true
},
{
"id": 2801,
"constant": "NS_COURSE_TALK",
"name": "Course_talk",
"subpages" : true
},
{
"id": 2900,
"constant": "NS_COURSEMETADATA",
"name": "CourseMetadata"
}
],
"config": {
"AjaxExportList": [
"CourseEditorOperations::manageCourseMetadataOp",
"CourseEditorOperations::createCourseOp",
"CourseEditorOperations::applySectionOp",
"CourseEditorOperations::applyCourseOp"
]
},
"SpecialPages": {
"CourseEditor": "SpecialCourseEditor"
},
"manifest_version":1
}
diff --git a/i18n/en.json b/i18n/en.json
index cfe00d0..6cf091d 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -1,52 +1,54 @@
{
"courseeditor" : "Course editor",
"courseeditor-managemetata-pagetitle": "Metadata management",
"courseeditor-credits-info": "CourseEditor is an extension to create and manage courses.",
"courseeditor-add-new-section" : "Add a new section",
"courseeditor-save-course": "Save course",
"courseeditor-add-new-chapter" : "Add New Chapter",
"courseeditor-save-section" : "Save Section",
"courseeditor-cancel" : "Cancel",
"courseeditor-edit-dialog" : "Edit",
"courseeditor-rename" : "Rename",
"courseeditor-organize-chapters" : "You can organize, add and delete chapters",
"courseeditor-organize-sections" : "You can organize, add and delete sections",
"courseeditor-input-department-label" : "Department:",
"courseeditor-input-topic-label" : "Topic:",
"courseeditor-input-course-label" : "Title:",
"courseeditor-input-course-placeholder" : "Insert the title of the course",
"courseeditor-input-description-label" : "Description:",
"courseeditor-input-description-placeholder" : "Insert a description",
"courseeditor-input-externalreferences-label" : "External references:",
"courseeditor-input-externalreferences-placeholder" : "Insert external references",
"courseeditor-input-reviewed-label" : "Reviewed",
"courseeditor-input-imported-label" : "Imported",
"courseeditor-input-originalauthors-label" : "Original authors:",
"courseeditor-input-originalauthors-placeholder" : "Insert the original authors",
"courseeditor-input-reviewedon-label" : "Reviewed on:",
"courseeditor-input-reviewedon-placeholder" : "Insert the date (dd/mm/yyyy)",
"courseeditor-save-button" : "Save",
"courseeditor-create-button" : "Create!",
"courseeditor-alert-message" : "Hey, there is a course with the same title yet!
Choose another title or start to contribute immediately to the existing course.",
"courseeditor-validate-form" : "Please, insert a topic and a name",
"courseeditor-radiobutton-namespace" : "Do you want to creatre a private course in your personal page or a public one?",
"courseeditor-radiobutton-namespace-private" : "Private",
"courseeditor-radiobutton-namespace-public" : "Public",
"courseeditor-message-dialog-title" : "Oops...",
"courseeditor-message-dialog-message" : "There's an element in the recycle bin with the same name, what do you want to do?",
"courseeditor-message-dialog-cancel" : "Cancel",
"courseeditor-message-dialog-restore" : "Restore",
"courseeditor-message-dialog-create-new" : "Create new",
"courseeditor-alert-message-existing-element" : "There is already an element with the same name. Please, enter a different one.",
"courseeditor-recycle-bin" : "Recycle bin",
"courseeditor-error-operation" : "Sorry, something went wrong! :(
",
"courseeditor-operation-action-add" : "Add",
- "courseeditor-operation-action-rename" : "Rename",
- "courseeditor-operation-action-delete" : "Delete",
+ "courseeditor-operation-action-rename-move-task" : "Rename",
+ "courseeditor-operation-action-rename-update-task" : "Update links",
+ "courseeditor-operation-action-delete-chapters-task" : "Delete chapters of",
+ "courseeditor-operation-action-delete-section-task" : "Delete ",
"courseeditor-operation-action-purge" : "Purge",
"courseeditor-operation-action-update" : "Update",
"courseeditor-operation-action-update-collection" : "Update book",
"courseeditor-error-operation-fail" : " fails!",
"courseeditor-collection-book-category": "Books",
"courseeditor-collection-savedbook-template": "saved_book"
}
diff --git a/i18n/it.json b/i18n/it.json
index b6cd82a..b0b324d 100644
--- a/i18n/it.json
+++ b/i18n/it.json
@@ -1,52 +1,54 @@
{
"courseeditor" : "Editor di corsi",
"courseeditor-managemetata-pagetitle": "Gestione metadati",
"courseeditor-credits-info": "CourseEditor è una estensione per creare ed organizzare corsi.",
"courseeditor-add-new-section" : "Aggiungi una nuova sezione",
"courseeditor-save-course": "Salva corso",
"courseeditor-add-new-chapter" : "Aggiungi un nuovo capitolo",
"courseeditor-save-section" : "Salva sezione",
"courseeditor-cancel" : "Cancella",
"courseeditor-edit-dialog" : "Modifica",
"courseeditor-rename" : "Rinomina",
"courseeditor-organize-chapters" : "Qui puoi organizzare, aggiungere e rimuovere capitoli",
"courseeditor-organize-sections" : "Qui puoi organizzare, aggiungere e rimuovere sezioni",
"courseeditor-input-department-label" : "Dipartmento:",
"courseeditor-input-topic-label" : "Argomento:",
"courseeditor-input-course-label" : "Titolo:",
"courseeditor-input-course-placeholder" : "Inserisci il titolo del corso",
"courseeditor-input-description-label" : "Descrizione:",
"courseeditor-input-description-placeholder" : "Insersci la descrizione",
"courseeditor-input-externalreferences-label" : "Riferimenti esterni:",
"courseeditor-input-externalreferences-placeholder" : "Inserisci i riferimenti esterni",
"courseeditor-input-reviewed-label" : "Revisionato",
"courseeditor-input-imported-label" : "Importato",
"courseeditor-input-originalauthors-label" : "Autori originali:",
"courseeditor-input-originalauthors-placeholder" : "Inserisci gli autori originali",
"courseeditor-input-reviewedon-label" : "Revisionato il:",
"courseeditor-input-reviewedon-placeholder" : "Inserisci la data (gg/mm/aaaa)",
"courseeditor-save-button" : "Salva",
"courseeditor-create-button" : "Crea!",
"courseeditor-alert-message" : "Ehi, c'è un corso con lo stesso titolo!
Scegli un altro titolo o inizia a contribuire subito al corso esitente.
",
"courseeditor-validate-form" : "Inserisci l'argomento e il corso!",
"courseeditor-radiobutton-namespace" : "Vuoi creare un corso privato nella tua pagina personale o uno pubblico?",
"courseeditor-radiobutton-namespace-private" : "Privato",
"courseeditor-radiobutton-namespace-public" : "Pubblico",
"courseeditor-message-dialog-title" : "Ops...",
"courseeditor-message-dialog-message" : "C'è un elemento nel cestino con lo stesso nome, cosa vuoi fare?",
"courseeditor-message-dialog-cancel" : "Indietro",
"courseeditor-message-dialog-restore" : "Ripristina",
"courseeditor-message-dialog-create-new" : "Crea nuovo",
"courseeditor-alert-message-existing-element" : "È già presente un elemento con lo stesso nome. Per favore, inserire un nome diverso.",
"courseeditor-recycle-bin" : "Cestino",
"courseeditor-error-operation" : "Scusa, qualcosa è andato storto! :(
",
"courseeditor-operation-action-add" : "Aggiungi",
- "courseeditor-operation-action-rename" : "Rinomina ",
- "courseeditor-operation-action-delete" : "Elimina",
+ "courseeditor-operation-action-rename-move-task" : "Rinomina ",
+ "courseeditor-operation-action-rename-update-task" : "Aggiorna links",
+ "courseeditor-operation-action-delete-chapters-task" : "Elimina capitoli di",
+ "courseeditor-operation-action-delete-section-task" : "Elimina",
"courseeditor-operation-action-purge" : "Purga",
"courseeditor-operation-action-update" : "Aggiorna",
"courseeditor-operation-action-update-collection" : "Aggiorna libro",
"courseeditor-error-operation-fail" : " fallito!",
"courseeditor-collection-book-category": "Libri",
"courseeditor-collection-savedbook-template": "libro_salvato"
}
diff --git a/modules/commonFunctions.js b/modules/commonFunctions.js
index c5a44c2..ecc68f0 100644
--- a/modules/commonFunctions.js
+++ b/modules/commonFunctions.js
@@ -1,465 +1,464 @@
/* Create a gloabal windowManager to open dialogs and append it to the body*/
var windowManager = new OO.ui.WindowManager();
$('body').append( windowManager.$element );
/******** UTIL METHODS ********/
var createMicroOperations = function(operation){
switch (operation.action) {
case 'rename':
return createRenameMicroOperations(operation);
break;
case 'delete':
return createDeleteMicroOperations(operation);
break;
default:
return createDefaultMicroOperations(operation);
}
};
var createDefaultMicroOperations = function(operation){
var microOps = [];
microOps.push(operation);
return microOps;
}
var createRenameMicroOperations = function(operation) {
var microOps = [];
microOps.push({
action: 'rename-move-task',
elementName: operation.elementName,
newElementName: operation.newElementName
});
microOps.push({
action: 'rename-update-task',
elementName: operation.elementName,
newElementName: operation.newElementName
});
return microOps;
};
var createDeleteMicroOperations = function(operation) {
var microOps = [];
microOps.push({
action: 'delete-chapters-task',
elementName: operation.elementName
});
microOps.push({
action: 'delete-section-task',
elementName: operation.elementName
});
return microOps;
};
/*
var createMicroDefaultOperations = function(operation, callback) {
var microOps = [];
microOps.push(operation);
callback(microOps);
};
var createMicroRenameOperations = function(operation, callback) {
var title = new mw.Title($('#courseName').text());
var microOps = [];
getSubpages(title, operation, function(subpages){
for (var i = 0; i < subpages.query.allpages.length; i++) {
var page = subpages.query.allpages[i];
//The better HACK ever: not return the callback until the for dosn't
// completed
if(i === subpages.query.allpages.length - 1) {
getMicroOpsFromBacklinks(page, operation, microOps, function(microOps) {
//Move the page and all its subpages
microOps.push(operation);
callback(microOps);
});
} else {
getMicroOpsFromBacklinks(page, operation, microOps, function(){});
}
}
});
};
var getMicroOpsFromBacklinks = function(page, operation, microOps, returnMicroOps){
var api = new mw.Api();
api.get( {
action: 'query',
list: 'backlinks',
bltitle: page.title,
} ).done( function ( data) {
if(data.query.backlinks.length > 0){
var backlinks = data.query.backlinks;
backlinks.shift(); //the course with transcluded pages
for (var i = 0; i < backlinks.length; i++) {
microOps.push({
action: 'fix-link',
elementName: backlinks[i].title,
linkToReplace: page.title,
replacement: operation.newElementName
});
}
}
returnMicroOps(microOps);
});
};
var getSubpages = function (title, operation, returnSubpages){
var api = new mw.Api();
api.get( {
action: 'query',
list: 'allpages',
apprefix: title.getMain() + "/" + operation.elementName,
apnamespace: title.getNamespaceId()
} ).done( function ( data) {
returnSubpages(data);
});
};*/
/**
* Init handlers
* @param {DraggableGroupWidget} [draggableWidget]
* @param {TextInputWidget} [textInputWidget]
* @param {Array} [editStack]
*/
var initHandlers = function(draggableWidget, textInputWidget, editStack){
$('.deleteElementIcon').click(function(){
deleteElement(draggableWidget, $(this).parent().text(), editStack);
});
$('.editElementIcon').click(function(){
editElement(draggableWidget, $(this).parent().text(), editStack);
});
$('.oo-ui-inputWidget-input').attr('id', 'addElement');
$('#addElement').blur(function(){
$('#alert').hide();
addElement(draggableWidget, textInputWidget.getValue(), editStack);
textInputWidget.setValue('');
});
$('#addElement').keypress(function(keypressed) {
if(keypressed.which === 13) {
addElement(draggableWidget, textInputWidget.getValue(), editStack);
textInputWidget.setValue('');
}
});
};
/**
* Find the index of a deleted element in the editStack
* @param {String} [elementName]
* @param {Array} [editStack]
*/
var findIndexOfDeletedElement = function(editStack, elementName) {
for (var i = 0; i < editStack.length; i++) {
if (editStack[i]['action'] === 'delete' && editStack[i]['elementName'] === elementName) {
return i;
}
}
return null;
};
/**
* Find the index of already added or renamed element in the editStack
* @param {String} [elementName]
* @param {DraggableWidget} [draggableWidget]
* @return boolean
*/
var elementExist = function(draggableWidget, elementName) {
var items = draggableWidget.getItems();
for (var item in items) {
if (items[item].data === elementName) {
return true;
}
}
return false;
};
/**
* Create a drag item, its handlers on edit and remove icons and append it to
* to the draggableWidget.
* @param {DraggableGroupWidget} [draggableWidget]
* @param {String} [elementName]
* @param {Array} [editStack]
*/
var createDragItem = function(draggableWidget, elementName, editStack){
//Create item and icons
var dragItem = new DraggableHandledItemWidget( {
data: elementName,
icon: 'menu',
label: elementName
} );
var iconDelete = $("");
var iconEdit = $("");
//Append icons and add the item to draggableWidget
dragItem.$label.append(iconDelete, iconEdit);
draggableWidget.addItems([dragItem]);
//Create handlers
$(iconDelete).click(function(){
deleteElement(draggableWidget, $(this).parent().text(), editStack);
});
$(iconEdit).click(function(){
editElement(draggableWidget, $(this).parent().text(), editStack);
});
};
/**
* Create a button list group item, its handler on undo and append it to
* to the RecycleBin list group.
* @param {DraggableGroupWidget} [draggableWidget]
* @param {String} [elementName]
* @param {Array} [editStack]
*/
var createRecycleBinItem = function(draggableWidget, elementName, editStack){
//Create item and icon
var liButton = $(' ' + elementName +'');
var undoDeleteIcon = $('');
//Append icon and add the item to the list
liButton.prepend(undoDeleteIcon);
$('.list-group').append(liButton);
//Create handler
$(undoDeleteIcon).click(function(){
var elementToRestore = $(this).parent().attr('id');
restoreElement(draggableWidget, elementToRestore, editStack);
});
}
/******** HELPER METHODS ********/
var dequeue = function(queueName){
$(document).dequeue(queueName);
};
/**
* Delete a element from the draggableWidget and add a item to the
* RecycleBin list.
* @param {DraggableGroupWidget} [draggableWidget]
* @param {String} [elementName]
* @param {Array} [editStack]
*/
var deleteElement = function(draggableWidget, elementName, editStack){
var elementToRemove = draggableWidget.getItemFromData(elementName);
draggableWidget.removeItems([elementToRemove]);
editStack.push({
action: 'delete',
elementName: elementName
});
createRecycleBinItem(draggableWidget, elementName, editStack);
};
/**
* Restore a element from the RecycleBin and remove its deletion
* from the editStack
* @param {DraggableGroupWidget} [draggableWidget]
* @param {String} [elementName]
* @param {Array} [editStack]
*/
var restoreElement = function(draggableWidget, elementName, editStack){
createDragItem(draggableWidget, elementName, editStack);
editStack.splice(editStack.indexOf({action: 'delete', element: elementName}));
$('li[id="' + elementName + '"]').remove();
};
/**
* Add a element to the draggableWidget automatically if its name isn't
* in the RecycleBin list, otherwise open a MessageDialog and ask to the user
* if he/she prefer to restore the element or create a new one.
* @param {DraggableGroupWidget} [draggableWidget]
* @param {String} [elementName]
* @param {Array} [editStack]
*/
var addElement = function(draggableWidget, elementName, editStack){
if($.trim(elementName).length !== 0){
if(findIndexOfDeletedElement(editStack, elementName) !== null){
var messageDialog = new OO.ui.MessageDialog();
windowManager.addWindows( [ messageDialog ] );
windowManager.openWindow( messageDialog, {
title: OO.ui.deferMsg('courseeditor-message-dialog-title'),
message: OO.ui.deferMsg('courseeditor-message-dialog-message'),
actions: [
{ action: 'reject', label: OO.ui.deferMsg('courseeditor-message-dialog-cancel'), flags: 'safe' },
{ action: 'restore', label: OO.ui.deferMsg('courseeditor-message-dialog-restore') },
{
action: 'confirm',
label: OO.ui.deferMsg('courseeditor-message-dialog-create-new'),
flags: [ 'primary', 'constructive' ]
}
]
} ).then( function ( opened ) {
opened.then( function ( closing, data ) {
if ( data && data.action === 'restore' ) {
restoreElement(draggableWidget, elementName, editStack);
} else if(data && data.action === 'confirm') {
createDragItem(draggableWidget, elementName, editStack);
editStack.push({
action: 'add',
elementName: elementName
});
}
} );
} );
}else if (elementExist(draggableWidget, elementName)) {
$('#alert').show();
}else {
createDragItem(draggableWidget, elementName, editStack);
editStack.push({
action: 'add',
elementName: elementName
});
}
}
};
/**
* Rename a element
* @param {DraggableGroupWidget} [draggableWidget]
* @param {String} [elementName]
* @param {Array} [editStack]
*/
var editElement = function(draggableWidget, elementName, editStack){
var dialog = new EditDialog(draggableWidget, elementName, editStack);
windowManager.addWindows( [ dialog ] );
windowManager.openWindow( dialog );
};
/******** OO.UI OBJECTS ********/
-//var progressBar = new OO.ui.ProgressBarWidget();
function ProgressDialog( config ) {
ProgressDialog.parent.call( this, config );
};
OO.inheritClass( ProgressDialog, OO.ui.Dialog );
ProgressDialog.static.escapable = false;
ProgressDialog.prototype.initialize = function () {
ProgressDialog.parent.prototype.initialize.call( this );
this.progressBar = new OO.ui.ProgressBarWidget({
progress: 0
});
this.currentOp = new OO.ui.LabelWidget( {
label: ''
} );
this.content = new OO.ui.PanelLayout( { padded: true, expanded: false } );
this.content.$element.append(this.progressBar.$element, this.currentOp.$element);
this.$body.append( this.content.$element );
};
ProgressDialog.prototype.getBodyHeight = function () {
return this.content.$element.outerHeight( true );
};
ProgressDialog.prototype.updateProgress = function(unitaryIncrement){
var currentProgress = this.progressBar.getProgress();
this.progressBar.setProgress(currentProgress + unitaryIncrement);
};
ProgressDialog.prototype.setCurrentOp = function(operation){
var labelToSet = OO.ui.msg('courseeditor-operation-action-' + operation.action);
if(operation.elementName){
labelToSet += " " + operation.elementName;
}
this.currentOp.setLabel(labelToSet);
};
/****** Draggable Widget ******/
/**
* Draggable group widget containing drag/drop items
*
* @param {Object} [config] Configuration options
*/
function DraggableGroupWidget( config ) {
// Configuration initialization
config = config || {};
// Parent constructor
DraggableGroupWidget.parent.call( this, config );
// Mixin constructors
OO.ui.mixin.DraggableGroupElement.call( this, $.extend( {}, config, { $group: this.$element } ) );
}
/* Setup */
OO.inheritClass( DraggableGroupWidget, OO.ui.Widget );
OO.mixinClass( DraggableGroupWidget, OO.ui.mixin.DraggableGroupElement );
/**
* Drag/drop items with custom handle
*
* @param {Object} [config] Configuration options
*/
function DraggableHandledItemWidget( config ) {
// Configuration initialization
config = config || {};
// Parent constructor
DraggableHandledItemWidget.parent.call( this, config );
// Mixin constructors
OO.ui.mixin.DraggableElement.call( this, $.extend( { $handle: this.$icon }, config ) );
}
/* Setup */
OO.inheritClass( DraggableHandledItemWidget, OO.ui.DecoratedOptionWidget );
OO.mixinClass( DraggableHandledItemWidget, OO.ui.mixin.DraggableElement );
/****** Edit Dialog ******/
/* Create a dialog */
function EditDialog(draggableWidget, elementName, editStack, config ) {
EditDialog.parent.call( this, config );
this.draggableWidget = draggableWidget;
this.elementName = elementName;
this.editStack = editStack;
this.textInputWidget = new OO.ui.TextInputWidget($.extend( { validate: 'non-empty' }, config ) );
this.textInputWidget.setValue(elementName);
}
/* Inheritance */
OO.inheritClass( EditDialog, OO.ui.ProcessDialog );
/* Static Properties */
EditDialog.static.title = OO.ui.deferMsg( 'courseeditor-edit-dialog' );
EditDialog.static.actions = [
{ action: 'save', label: OO.ui.deferMsg( 'courseeditor-rename' ), flags: 'primary' },
{ label: OO.ui.deferMsg( 'courseeditor-cancel' ), flags: 'safe' }
];
/* Initialize the dialog elements */
EditDialog.prototype.initialize = function () {
EditDialog.parent.prototype.initialize.apply( this, arguments );
this.content = new OO.ui.PanelLayout( { padded: true, expanded: false } );
this.content.$element.append(this.textInputWidget.$element );
this.$body.append( this.content.$element );
};
/* Define actions */
EditDialog.prototype.getActionProcess = function ( action ) {
var dialog = this;
if ( action === 'save' ) {
return new OO.ui.Process( function () {
var newElementName = dialog.textInputWidget.getValue();
var items = dialog.draggableWidget.getItems();
items.filter(function(element) {
if(element.data === dialog.elementName){
element.setData(newElementName);
element.setLabel(newElementName);
var iconDelete = $("");
var iconEdit = $("");
element.$label.append(iconDelete, iconEdit);
$(iconDelete).click(function(){
deleteElement(dialog.draggableWidget, $(this).parent().text(), dialog.editStack);
});
$(iconEdit).click(function(){
editElement(dialog.draggableWidget, $(this).parent().text(), dialog.editStack);
});
dialog.editStack.push({
action: 'rename',
elementName: dialog.elementName,
newElementName: newElementName
})
}
});
dialog.close( { action: action } );
} );
}
return EditDialog.parent.prototype.getActionProcess.call( this, action );
};
diff --git a/modules/courseEditor.js b/modules/courseEditor.js
index 946f513..a256dcb 100644
--- a/modules/courseEditor.js
+++ b/modules/courseEditor.js
@@ -1,138 +1,136 @@
$(function () {
var dragElements = [];
//Add all existing sections to the dragSections array
$.each(sections, function(key, value){
var dragItem = new DraggableHandledItemWidget( {
data: value,
icon: 'menu',
label: value
} );
dragItem.$label.append("",
"");
dragElements.push(dragItem);
});
//Create a draggableWidget with the items in the dragSections array
var draggableWidget = new DraggableGroupWidget( {
items: dragElements
} );
var fieldDrag = new OO.ui.FieldLayout(draggableWidget);
//Create a textInputWidget for new sections
var textInputWidget = new OO.ui.TextInputWidget( { placeholder: OO.ui.deferMsg( 'courseeditor-add-new-section' ) } );
var fieldInput = new OO.ui.FieldLayout( textInputWidget);
//Append all created elements to DOM
$('#sectionsList').append(fieldDrag.$element, fieldInput.$element);
initHandlers(draggableWidget, textInputWidget, editStack);
$('#saveCourseButton').click(function(){
var newSections = [];
$.each(draggableWidget.getItems(), function(key, value){
newSections.push(value.data);
});
editStack.push({
action: 'update',
elementsList: JSON.stringify(newSections)
});
editStack.push({
action: 'update-collection'
});
var progressDialog = new ProgressDialog( {
size: 'medium'
} );
var unitaryIncrement = 100/editStack.length;
windowManager.addWindows( [ progressDialog ] );
windowManager.openWindow( progressDialog );
var doTask = function(microOp, next){
progressDialog.setCurrentOp(microOp);
$.getJSON( mw.util.wikiScript(), {
action: 'ajax',
rs: 'CourseEditorOperations::applyCourseOp',
rsargs: [$('#courseName').text(), JSON.stringify(microOp)]
}, function ( data ) {
- console.log(data);
- if (data.success !== true) {
- var alert = '
';
- $('#saveDiv').after(alert);
+ if (data.success !== true){
$('#alert').html(OO.ui.deferMsg('courseeditor-error-operation'));
$('#alert').append(OO.ui.deferMsg('courseeditor-operation-action-' + data.action));
if(data.elementName){
var localizedMsg = " " + data.elementName + OO.ui.msg('courseeditor-error-operation-fail');
$('#alert').append(localizedMsg);
}else {
$('#alert').append(OO.ui.deferMsg('courseeditor-error-operation-fail'));
}
+ $('#alert').show();
windowManager.closeWindow(progressDialog);
$(document).clearQueue('tasks');
}else {
progressDialog.updateProgress(unitaryIncrement);
next();
}
});
};
var createTask = function(microOp){
return function(next){
doTask(microOp, next);
}
};
/*function prepareCreateMicroOperations(operation) {
var dfd=$.Deferred();
createMicroOperations(operation, function(microOps){
for (var i = 0; i < microOps.length; i++) {
console.log(microOps[i]);
$(document).queue('tasks', createTask(microOps[i]));
}
dfd.resolve();
});
return dfd.promise();
}
var promises = [];
while (editStack.length > 0) {
var operation = editStack.shift();
promises.push(prepareCreateMicroOperations(operation));
}
$.when.apply($, promises).done(function(){
$(document).queue('tasks', createTask({
action: 'update',
elementsList: JSON.stringify(newSections)
}));
$(document).queue('tasks', createTask({
action: 'update-collection'
}));
$(document).queue('tasks', function(){
windowManager.closeWindow(progressDialog);
//window.location.assign('/' + $('#courseName').text());
});
dequeue('tasks');
});*/
while( editStack.length > 0) {
var operation = editStack.shift();
var microOps = createMicroOperations(operation);
for (var i = 0; i < microOps.length; i++) {
$(document).queue('tasks', createTask(microOps[i]));
}
};
$(document).queue('tasks', function(){
windowManager.closeWindow(progressDialog);
window.location.assign('/' + $('#courseName').text());
});
dequeue('tasks');
});
})
diff --git a/modules/createCourse.js b/modules/createCourse.js
index 4557a33..315f27b 100644
--- a/modules/createCourse.js
+++ b/modules/createCourse.js
@@ -1,95 +1,100 @@
$(function () {
var delay = (function(){
var timer = 0;
return function(callback, ms){
clearTimeout (timer);
timer = setTimeout(callback, ms);
};
})();
$('#courseName').keypress(function() {
delay(function(){
$('#alert').hide();
$('#createCourseButton').removeAttr('disabled');
if($.trim($('#courseName').val()).length !== 0){
var api = new mw.Api();
if($('#courseTopic').length !== 0){
api.get({
action : 'query',
titles : 'Course:' + $('#courseName').val().trim()
}
).done( function ( data ) {
var pages = data.query.pages;
if (!pages['-1']) {
for (var pageId in pages) {
- if (pages.hasOwnProperty(pagesId)) {
+ if (pages.hasOwnProperty(pageId)) {
$('#coursesList').html('' + pages[pageId].title + '
');
}
}
$('#createCourseButton').attr('disabled', true);
$('#alert').show();
}
} );
}else {
api.get({
action : 'query',
list : 'prefixsearch',
pssearch : $('#courseName').val().trim(),
psnamespace: '2800',
psprofile: 'classic'
}).done( function ( data ) {
$('#coursesList').html('');
var resultsArray = data.query.prefixsearch;
if (resultsArray.length > 0) {
for (var i = 0; i < resultsArray.length; i++){
//Exit when the result is a subpage
if(resultsArray[i].title.indexOf('/') >= 0) break;
$('#coursesList').append('' + resultsArray[i].title + '
');
}
$('#createCourseButton').attr('disabled', true);
$('#alert').show();
}
});
}
}
}, 500 );
});
$('#createCourseButton').click(function(e){
e.preventDefault();
var courseName = $('#courseName').val().trim();
var courseDescription = $('#courseDescription').val().trim();
var courseNamespace = $('input[name="courseNamespace"]:checked').val();
var courseTopic, courseDepartment, operationRequested;
if($('#courseTopic').length !== 0){
courseTopic = $('#courseTopic').val().trim();
operationRequested = {
type : 'fromTopic',
params : [
courseTopic,
courseName,
courseDescription,
courseNamespace
]
};
}else{
courseDepartment = $('#courseDepartment').val().trim();
operationRequested = {
type : 'fromDepartment',
params : [
courseDepartment,
courseName,
courseDescription,
courseNamespace
]
};
}
$.post( mw.util.wikiScript(), {
action: 'ajax',
rs: 'CourseEditorOperations::createCourseOp',
rsargs: [JSON.stringify(operationRequested)]
- }, function ( data ) {
- //window.location.assign('/' + courseTopic);
+ }, function ( result ) {
+ var resultObj = JSON.parse(result);
+ if(resultObj.success !== true){
+ $('#alertError').show();
+ }else {
+ window.location.assign('/' + resultObj.courseTitle);
+ }
});
});
})
diff --git a/modules/sectionEditor.js b/modules/sectionEditor.js
index 4f6385a..2e0038b 100644
--- a/modules/sectionEditor.js
+++ b/modules/sectionEditor.js
@@ -1,97 +1,100 @@
$(function () {
var dragElements = [];
//Add all existing chapters to the dragElements array
$.each(chapters, function(key, value){
var dragItem = new DraggableHandledItemWidget( {
data: value,
icon: 'menu',
label: value
} );
dragItem.$label.append("",
"");
dragElements.push(dragItem);
});
//Create a draggableWidget with the items in the dragElements array
var draggableWidget = new DraggableGroupWidget( {
items: dragElements
} );
var fieldDrag = new OO.ui.FieldLayout(draggableWidget);
//Create a textInputWidget for new chapters
var textInputWidget = new OO.ui.TextInputWidget( { placeholder: OO.ui.deferMsg( 'courseeditor-add-new-chapter' ) } );
var fieldInput = new OO.ui.FieldLayout( textInputWidget);
//Append all created elements to DOM
$('#chaptersList').append(fieldDrag.$element, fieldInput.$element);
//Init Handlers
initHandlers(draggableWidget, textInputWidget, editStack);
$('#saveSectionButton').click(function(){
var newChapters = [];
$.each(draggableWidget.getItems(), function(key, value){
newChapters.push(value.data);
});
editStack.push({
action: 'update',
elementsList: JSON.stringify(newChapters)
});
editStack.push({
action: 'purge'
});
editStack.push({
action: 'update-collection'
});
var progressDialog = new ProgressDialog( {
size: 'medium'
} );
+ var unitaryIncrement = 100/editStack.length;
+
windowManager.addWindows( [ progressDialog ] );
windowManager.openWindow( progressDialog );
var createTask = function(operation){
return function(next){
doTask(operation, next);
}
};
var doTask = function(operation, next){
+ progressDialog.setCurrentOp(operation);
$.getJSON( mw.util.wikiScript(), {
action: 'ajax',
rs: 'CourseEditorOperations::applySectionOp',
rsargs: [$('#sectionName').text(), JSON.stringify(operation)]
}, function ( data ) {
if (data.success !== true) {
- var alert = '
';
- $('#saveDiv').after(alert);
$('#alert').html(OO.ui.msg('courseeditor-error-operation'));
- $('#alert').append(OO.ui.msg('courseeditor-error-operation-action-' + data.action));
+ $('#alert').append(OO.ui.msg('courseeditor-operation-action-' + data.action));
if(data.elementName){
var localizedMsg = " " + data.elementName + OO.ui.msg('courseeditor-error-operation-fail');
$('#alert').append(localizedMsg);
}else {
$('#alert').append(OO.ui.msg('courseeditor-error-operation-fail'));
}
+ $('#alert').show();
windowManager.closeWindow(progressDialog);
$(document).clearQueue('tasks');
}else{
+ progressDialog.updateProgress(unitaryIncrement);
next();
}
});
};
while( editStack.length > 0 ) {
var operation = editStack.shift();
$(document).queue('tasks', createTask(operation));
};
$(document).queue('tasks', function(){
windowManager.closeWindow(progressDialog);
window.location.assign('/' + $('#sectionName').text());
});
dequeue('tasks')
});
})