<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><style type="text/css"><!--
#msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; }
#msg ul, pre { overflow: auto; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<title>[GlotPress] [466] trunk: Translation set syncing between projects</title>
</head>
<body>
<div id="msg">
<dl>
<dt>Revision</dt> <dd>466</dd>
<dt>Author</dt> <dd>nbachiyski</dd>
<dt>Date</dt> <dd>2010-04-09 15:23:52 +0000 (Fri, 09 Apr 2010)</dd>
</dl>
<h3>Log Message</h3>
<pre>Translation set syncing between projects</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkcssstylecss">trunk/css/style.css</a></li>
<li><a href="#trunkgpincludesassetsloaderphp">trunk/gp-includes/assets-loader.php</a></li>
<li><a href="#trunkgpincludesmiscphp">trunk/gp-includes/misc.php</a></li>
<li><a href="#trunkgpincludesroutes_mainphp">trunk/gp-includes/routes/_main.php</a></li>
<li><a href="#trunkgpincludesroutesprojectphp">trunk/gp-includes/routes/project.php</a></li>
<li><a href="#trunkgpincludesroutestranslationsetphp">trunk/gp-includes/routes/translation-set.php</a></li>
<li><a href="#trunkgpincludesroutesphp">trunk/gp-includes/routes.php</a></li>
<li><a href="#trunkgpincludestemplatephp">trunk/gp-includes/template.php</a></li>
<li><a href="#trunkgpincludesthingsprojectphp">trunk/gp-includes/things/project.php</a></li>
<li><a href="#trunkgptemplatesfooterphp">trunk/gp-templates/footer.php</a></li>
<li><a href="#trunkgptemplatesprojectformphp">trunk/gp-templates/project-form.php</a></li>
<li><a href="#trunkgptemplatesprojectphp">trunk/gp-templates/project.php</a></li>
<li><a href="#trunkgptemplatestranslationsetformphp">trunk/gp-templates/translation-set-form.php</a></li>
<li><a href="#trunkjscommonjs">trunk/js/common.js</a></li>
<li><a href="#trunkjstranslationspagejs">trunk/js/translations-page.js</a></li>
<li><a href="#trunkttest_miscphp">trunk/t/test_misc.php</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkgptemplatesprojectmasscreatesetsphp">trunk/gp-templates/project-mass-create-sets.php</a></li>
<li><a href="#trunkjsmasscreatesetspagejs">trunk/js/mass-create-sets-page.js</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkcssstylecss"></a>
<div class="modfile"><h4>Modified: trunk/css/style.css (465 => 466)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/css/style.css        2010-04-08 14:23:31 UTC (rev 465)
+++ trunk/css/style.css        2010-04-09 15:23:52 UTC (rev 466)
</span><span class="lines">@@ -2,6 +2,8 @@
</span><span class="cx">         font-family: "Helvetica", "Arial", sans-serif;
</span><span class="cx">         color: #333;
</span><span class="cx">         line-height: 1.5em;
</span><ins>+        font-size: 14px;
+        margin: 0 .5em 0 .5em;
</ins><span class="cx"> }
</span><span class="cx"> input, textarea {
</span><span class="cx"> font-size: 1em;
</span><span class="lines">@@ -27,6 +29,10 @@
</span><span class="cx"> a img {
</span><span class="cx"> border: 0;
</span><span class="cx"> }
</span><ins>+a.disabled {
+ color: #aaa;
+ text-decoration: none;
+}
</ins><span class="cx"> h2 {
</span><span class="cx"> border-bottom: 0.08em solid #CCC;
</span><span class="cx"> }
</span><span class="lines">@@ -405,3 +411,9 @@
</span><span class="cx">         padding-left: 1em;
</span><span class="cx">         border-left: 3px solid #aaa;
</span><span class="cx"> }
</span><ins>+span.added {
+ color: green;
+}
+span.removed {
+ color: red;
+}
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkgpincludesassetsloaderphp"></a>
<div class="modfile"><h4>Modified: trunk/gp-includes/assets-loader.php (465 => 466)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-includes/assets-loader.php        2010-04-08 14:23:31 UTC (rev 465)
+++ trunk/gp-includes/assets-loader.php        2010-04-09 15:23:52 UTC (rev 466)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx">         $scripts->add( 'common', '/common.js', array( 'jquery' ) );
</span><span class="cx">         $scripts->add( 'editor', '/editor.js', array( 'common', 'google-js-api' ) );
</span><span class="cx">         $scripts->add( 'translations-page', '/translations-page.js', array( 'common' ) );
</span><ins>+        $scripts->add( 'mass-create-sets-page', '/mass-create-sets-page.js', array( 'common' ) );
</ins><span class="cx">         $scripts->add( 'google-js-api', 'http://www.google.com/jsapi', array(), '' );
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkgpincludesmiscphp"></a>
<div class="modfile"><h4>Modified: trunk/gp-includes/misc.php (465 => 466)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-includes/misc.php        2010-04-08 14:23:31 UTC (rev 465)
+++ trunk/gp-includes/misc.php        2010-04-09 15:23:52 UTC (rev 466)
</span><span class="lines">@@ -43,7 +43,6 @@
</span><span class="cx">         return isset( $object->$key )? $object->$key : $default;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-
</del><span class="cx"> /**
</span><span class="cx"> * Makes from an array of arrays a flat array.
</span><span class="cx"> *
</span><span class="lines">@@ -268,4 +267,22 @@
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx">         return $res;
</span><ins>+}
+
+function gp_array_any( $callback, $array ) {
+        foreach( $array as $item ) {
+                if ( $callback( $item ) ) {
+                        return true;
+                }
+        }
+        return false;
+}
+
+function gp_array_all( $callback, $array ) {
+        foreach( $array as $item ) {
+                if ( !$callback( $item ) ) {
+                        return false;
+                }
+        }
+        return false;
</ins><span class="cx"> }
</span><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkgpincludesroutes_mainphp"></a>
<div class="modfile"><h4>Modified: trunk/gp-includes/routes/_main.php (465 => 466)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-includes/routes/_main.php        2010-04-08 14:23:31 UTC (rev 465)
+++ trunk/gp-includes/routes/_main.php        2010-04-09 15:23:52 UTC (rev 466)
</span><span class="lines">@@ -3,42 +3,4 @@
</span><span class="cx"> * Holds common functionality for routes.
</span><span class="cx"> */
</span><span class="cx"> class GP_Route_Main extends GP_Route {
</span><del>-        // TODO: move these as a template helper
-        
-        function _options_from_projects( $projects ) {
-                // TODO: mark which nodes are editable by the current user
-                $tree = array();
-                $top = array();
-                foreach( $projects as $p ) {
-                        $tree[$p->id]['self'] = $p;
-                        if ( $p->parent_project_id ) {
-                                $tree[$p->parent_project_id]['children'][] = $p->id;
-                        } else {
-                                $top[] = $p->id;
-                        }
-                }
-                $options = array( '' => __('No parent') );
-                $stack = array();
-                foreach( $top as $top_id ) {
-                        $stack = array( $top_id );
-                        while ( !empty( $stack ) ) {
-                                $id = array_pop( $stack );
-                                $tree[$id]['level'] = gp_array_get( $tree[$id], 'level', 0 );
-                                $options[$id] = str_repeat( '-', $tree[$id]['level'] ) . $tree[$id]['self']->name;
-                                foreach( gp_array_get( $tree[$id], 'children', array() ) as $child_id ) {
-                                        $stack[] = $child_id;
-                                        $tree[$child_id]['level'] = $tree[$id]['level'] + 1;
-                                }
-                        }
-                }
-                return $options;
-        }
-
-        function _options_from_locales( $locales ) {
-                $values = array_map( create_function( '$l', 'return $l->slug;'), $locales );
-                $labels = array_map( create_function( '$l', 'return $l->slug." - ". $l->english_name;'), $locales );
-                sort( $values );
-                sort( $labels );
-                return array_combine($values, $labels);
-        }
</del><span class="cx"> }
</span></span></pre></div>
<a id="trunkgpincludesroutesprojectphp"></a>
<div class="modfile"><h4>Modified: trunk/gp-includes/routes/project.php (465 => 466)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-includes/routes/project.php        2010-04-08 14:23:31 UTC (rev 465)
+++ trunk/gp-includes/routes/project.php        2010-04-09 15:23:52 UTC (rev 466)
</span><span class="lines">@@ -70,7 +70,6 @@
</span><span class="cx">                 $project = GP::$project->by_path( $project_path );
</span><span class="cx">                 if ( !$project ) gp_tmpl_404();
</span><span class="cx">                 $this->can_or_redirect( 'write', 'project', $project->id );
</span><del>-                $all_project_options = self::_options_from_projects( GP::$project->all() );
</del><span class="cx">                 gp_tmpl_load( 'project-edit', get_defined_vars() );
</span><span class="cx">         }
</span><span class="cx">         
</span><span class="lines">@@ -111,7 +110,6 @@
</span><span class="cx">                 $project = new GP_Project();
</span><span class="cx">                 $project->parent_project_id = gp_get( 'parent_project_id', null );
</span><span class="cx">                 $this->can_or_redirect( 'write', 'project', $project->parent_project_id );
</span><del>-                $all_project_options = self::_options_from_projects( GP::$project->all() );
</del><span class="cx">                 gp_tmpl_load( 'project-new', get_defined_vars() );
</span><span class="cx">         }
</span><span class="cx">         
</span><span class="lines">@@ -125,7 +123,6 @@
</span><span class="cx">                 if ( !$project ) {
</span><span class="cx">                         $project = new GP_Project();
</span><span class="cx">                         $this->errors[] = __('Error in creating project!');
</span><del>-                        $all_project_options = self::_options_from_projects( GP::$project->all() );
</del><span class="cx">                         gp_tmpl_load( 'project-new', get_defined_vars() );
</span><span class="cx">                 } else {
</span><span class="cx">                         $this->notices[] = __('The project was created!');
</span><span class="lines">@@ -197,4 +194,47 @@
</span><span class="cx">                 }
</span><span class="cx">                 gp_redirect( gp_url_project( $project, array( '-permissions' ) ) );
</span><span class="cx">         }
</span><ins>+
+        function mass_create_sets_get( $project_path ) {
+                $project = GP::$project->by_path( $project_path );
+                if ( !$project ) gp_tmpl_404();
+                $this->can_or_redirect( 'write', 'project', $project->id );
+                $this->tmpl( 'project-mass-create-sets', get_defined_vars() );
+        }
+
+        function mass_create_sets_post( $project_path ) {
+                $project = GP::$project->by_path( $project_path );
+                if ( !$project ) gp_tmpl_404();
+                $this->can_or_redirect( 'write', 'project', $project->id );
+                $other_project = GP::$project->get( gp_post( 'project_id' ) );
+                if ( !$other_project ) {
+                        $this->die_with_error( __('Project wasn&#8217;found') );
+                }
+                $changes = $project->set_difference_from( $other_project );
+                $errors = 0;
+                foreach( $changes['added'] as $to_add ) {
+                        if ( !GP::$translation_set->create( array('project_id' => $project->id, 'name' => $to_add->name, 'locale' => $to_add->locale, 'slug' => $to_add->slug) ) ) {
+                                $this->errors[] = __('Couldn&#8217;t add translation set named %s', esc_html( $to_add->name ) );
+                        }
+                }
+                foreach( $changes['removed'] as $to_remove ) {
+                        if ( !$to_remove->delete() ) {
+                                $this->errors[] = __('Couldn&#8217;t delete translation set named %s', esc_html( $to_remove->name ) );
+                        }
+                }
+                if ( !$this->errors ) $this->notices[] = __('Translation sets were added and removed successfully');
+                gp_redirect( gp_url_project( $project ) );
+        }
+
+        function mass_create_sets_preview_post( $project_path ) {
+                $project = GP::$project->by_path( $project_path );
+                if ( !$project ) gp_tmpl_404();
+                $this->can_or_redirect( 'write', 'project', $project->id );
+                $other_project = GP::$project->get( gp_post( 'project_id' ) );
+                if ( !$other_project ) {
+                        $this->die_with_error( __('Project wasn&#8217;found') );
+                }
+                header('Content-Type: application/json');
+                echo json_encode( $project->set_difference_from( $other_project ) );
+        }        
</ins><span class="cx"> }
</span><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkgpincludesroutestranslationsetphp"></a>
<div class="modfile"><h4>Modified: trunk/gp-includes/routes/translation-set.php (465 => 466)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-includes/routes/translation-set.php        2010-04-08 14:23:31 UTC (rev 465)
+++ trunk/gp-includes/routes/translation-set.php        2010-04-09 15:23:52 UTC (rev 466)
</span><span class="lines">@@ -6,8 +6,6 @@
</span><span class="cx">                 if ( $set->project_id ) {
</span><span class="cx">                         $this->can_or_redirect( 'write', 'project', $set->project_id, gp_url_project( GP::$project->get( $set->project_id ) ) );
</span><span class="cx">                 }
</span><del>-                $all_project_options = self::_options_from_projects( GP::$project->all() );
-                $all_locale_options = self::_options_from_locales( GP_Locales::locales() );
</del><span class="cx">                 gp_tmpl_load( 'translation-set-new', get_defined_vars() );
</span><span class="cx">         }
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkgpincludesroutesphp"></a>
<div class="modfile"><h4>Modified: trunk/gp-includes/routes.php (465 => 466)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-includes/routes.php        2010-04-08 14:23:31 UTC (rev 465)
+++ trunk/gp-includes/routes.php        2010-04-09 15:23:52 UTC (rev 466)
</span><span class="lines">@@ -58,6 +58,10 @@
</span><span class="cx">                         "post:/$project/-permissions" => array('GP_Route_Project', 'permissions_post'),
</span><span class="cx">                         "get:/$project/-permissions/-delete/$dir" => array('GP_Route_Project', 'permissions_delete'),
</span><span class="cx">                         
</span><ins>+                        "get:/$project/-mass-create-sets" => array('GP_Route_Project', 'mass_create_sets_get'),
+                        "post:/$project/-mass-create-sets" => array('GP_Route_Project', 'mass_create_sets_post'),
+                        "post:/$project/-mass-create-sets/preview" => array('GP_Route_Project', 'mass_create_sets_preview_post'),
+                        
</ins><span class="cx">
</span><span class="cx">                         "get:/$projects" => array('GP_Route_Project', 'index'),
</span><span class="cx">                         "get:/$projects/-new" => array('GP_Route_Project', 'new_get'),
</span></span></pre></div>
<a id="trunkgpincludestemplatephp"></a>
<div class="modfile"><h4>Modified: trunk/gp-includes/template.php (465 => 466)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-includes/template.php        2010-04-08 14:23:31 UTC (rev 465)
+++ trunk/gp-includes/template.php        2010-04-09 15:23:52 UTC (rev 466)
</span><span class="lines">@@ -29,7 +29,6 @@
</span><span class="cx">         gp_tmpl_load( 'footer', $args );
</span><span class="cx"> }
</span><span class="cx">
</span><del>-
</del><span class="cx"> function gp_head() {
</span><span class="cx">         do_action( 'gp_head' );
</span><span class="cx"> }
</span><span class="lines">@@ -165,10 +164,41 @@
</span><span class="cx">         return $attrs;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-function gp_locales_dropdown( $name_and_id, $selected_slug = '', $attrs = array() ) {
-        $options = array( '' => '&mdash; Locale &mdash;' );
-        foreach( GP_Locales::locales() as $locale ) {
-                $options[$locale->slug] = sprintf( '%s &ndash; %s', $locale->slug, $locale->english_name );
</del><ins>+function gp_locales_dropdown( $name_and_id, $selected_slug = null, $attrs = array() ) {
+        $locales = GP_Locales::locales();
+        $values = array_map( create_function( '$l', 'return $l->slug;'), $locales );
+        $labels = array_map( create_function( '$l', 'return $l->slug." &mdash; ". $l->english_name;'), $locales );
+        sort( $values );
+        sort( $labels );
+        return gp_select( $name_and_id, array_merge( array( '' => __('&mdash; Locale &mdash;') ), array_combine( $values, $labels ) ), $selected_slug, $attrs );
+}
+
+function gp_projects_dropdown( $name_and_id, $selected_project_id = null, $attrs = array() ) {
+        $projects = GP::$project->all();
+        // TODO: mark which nodes are editable by the current user
+        $tree = array();
+        $top = array();
+        foreach( $projects as $p ) {
+                $tree[$p->id]['self'] = $p;
+                if ( $p->parent_project_id ) {
+                        $tree[$p->parent_project_id]['children'][] = $p->id;
+                } else {
+                        $top[] = $p->id;
+                }
</ins><span class="cx">         }
</span><del>-        return gp_select( $name_and_id, $options, $selected_slug, $attrs );
</del><ins>+        $options = array( '' => __('&mdash; No parent &mdash;') );
+        $stack = array();
+        foreach( $top as $top_id ) {
+                $stack = array( $top_id );
+                while ( !empty( $stack ) ) {
+                        $id = array_pop( $stack );
+                        $tree[$id]['level'] = gp_array_get( $tree[$id], 'level', 0 );
+                        $options[$id] = str_repeat( '-', $tree[$id]['level'] ) . $tree[$id]['self']->name;
+                        foreach( gp_array_get( $tree[$id], 'children', array() ) as $child_id ) {
+                                $stack[] = $child_id;
+                                $tree[$child_id]['level'] = $tree[$id]['level'] + 1;
+                        }
+                }
+        }
+        return gp_select( $name_and_id, $options, $selected_project_id, $attrs );
</ins><span class="cx"> }
</span><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkgpincludesthingsprojectphp"></a>
<div class="modfile"><h4>Modified: trunk/gp-includes/things/project.php (465 => 466)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-includes/things/project.php        2010-04-08 14:23:31 UTC (rev 465)
+++ trunk/gp-includes/things/project.php        2010-04-09 15:23:52 UTC (rev 466)
</span><span class="lines">@@ -127,5 +127,25 @@
</span><span class="cx">                 }
</span><span class="cx">                 return array_merge( array( &$this ), $path );
</span><span class="cx">         }
</span><ins>+        
+        function set_difference_from( $other_project ) {
+                $this_sets = (array)GP::$translation_set->by_project_id( $this->id );
+                $other_sets = (array)GP::$translation_set->by_project_id( $other_project->id );
+                $added = array();
+                $removed = array();
+                foreach( $other_sets as $other_set ) {
+                        $vars = array( 'locale' => $other_set->locale, 'slug' => $other_set->slug );
+                        if ( !gp_array_any( lambda('$set', '$set->locale == $locale && $set->slug == $slug', $vars ), $this_sets ) ) {
+                                $added[] = $other_set;
+                        }
+                }
+                foreach( $this_sets as $this_set ) {
+                        $vars = array( 'locale' => $this_set->locale, 'slug' => $this_set->slug );
+                        if ( !gp_array_any( lambda('$set', '$set->locale == $locale && $set->slug == $slug', $vars ), $other_sets ) ) {
+                                $removed[] = $this_set;
+                        }
+                }
+                return compact( 'added', 'removed' );
+        }
</ins><span class="cx"> }
</span><span class="cx"> GP::$project = new GP_Project();
</span><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkgptemplatesfooterphp"></a>
<div class="modfile"><h4>Modified: trunk/gp-templates/footer.php (465 => 466)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-templates/footer.php        2010-04-08 14:23:31 UTC (rev 465)
+++ trunk/gp-templates/footer.php        2010-04-09 15:23:52 UTC (rev 466)
</span><span class="lines">@@ -1,4 +1,4 @@
</span><del>-        <p id="footer"class="secondary">
</del><ins>+        <p id="footer" class="secondary">
</ins><span class="cx">                 <?php printf( __('Proudly powered by <a href="%s" title="Found in translation">GlotPress</a>.'), 'http://glotpress.org/' ); ?>
</span><span class="cx">                 <?php gp_footer(); ?>
</span><span class="cx">         </p>
</span></span></pre></div>
<a id="trunkgptemplatesprojectformphp"></a>
<div class="modfile"><h4>Modified: trunk/gp-templates/project-form.php (465 => 466)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-templates/project-form.php        2010-04-08 14:23:31 UTC (rev 465)
+++ trunk/gp-templates/project-form.php        2010-04-09 15:23:52 UTC (rev 466)
</span><span class="lines">@@ -19,7 +19,7 @@
</span><span class="cx">         </dd>
</span><span class="cx">
</span><span class="cx">         <dt><label for="project[parent_project_id]"><?php _e('Parent Project'); ?></label></dt>
</span><del>-        <dd><?php echo gp_select( 'project[parent_project_id]', $all_project_options, $project->parent_project_id); ?></dd>
</del><ins>+        <dd><?php echo gp_projects_dropdown( 'project[parent_project_id]', $project->parent_project_id); ?></dd>
</ins><span class="cx"> </dl>
</span><span class="cx">
</span><span class="cx"> <?php echo gp_js_focus_on( 'project[name]' ); ?>
</span></span></pre></div>
<a id="trunkgptemplatesprojectmasscreatesetsphp"></a>
<div class="addfile"><h4>Added: trunk/gp-templates/project-mass-create-sets.php (0 => 466)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-templates/project-mass-create-sets.php         (rev 0)
+++ trunk/gp-templates/project-mass-create-sets.php        2010-04-09 15:23:52 UTC (rev 466)
</span><span class="lines">@@ -0,0 +1,25 @@
</span><ins>+<?php
+gp_title( sprintf( __( 'Mass-create Translation Sets &lt; %s &lt; GlotPress' ), $project->name ) );
+gp_breadcrumb( array(
+        gp_link_project_get( $project, $project->name ),
+) );
+wp_enqueue_script( 'mass-create-sets-page' );
+wp_localize_script( 'mass-create-sets-page', '$gp_mass_create_sets_options', array(
+        'url' => gp_url_join( gp_url_current(), 'preview'),
+        'loading' => __('Loading translation sets to create&hellip;'),
+));
+gp_tmpl_header();
+?>
+<h2><?php _e( sprintf( __('Mass-create Project Sets in <q>%s</q>'), esc_html( $project->name ) ) ); ?></h2>
+<p><?php _e('Here you can mass-create translation sets in this project.
+The list of translation sets will be mirrored with the sets of a project you choose.
+Usually this is one of the parent projects.'); ?></p>
+<form action="<?php echo esc_url( gp_url_current() ); ?>" method="post">
+        <dl>
+                <dt><label for="project_id"><?php _e('Project to take translation sets from:'); ?></label></dt>
+                <dd><?php echo gp_projects_dropdown( 'project_id', $project->parent_project_id ); ?></dd>
+        </dl>
+        <div id="preview"></div>
+        <p><input type="submit" name="submit" value="<?php echo esc_attr( __('Create Translation Sets') ); ?>" id="submit" /></p>
+</form>
+<?php gp_tmpl_footer();
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/gp-templates/project-mass-create-sets.php
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:eol-style
</span><span class="cx"> + native
</span></span></pre></div>
<a id="trunkgptemplatesprojectphp"></a>
<div class="modfile"><h4>Modified: trunk/gp-templates/project.php (465 => 466)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-templates/project.php        2010-04-08 14:23:31 UTC (rev 465)
+++ trunk/gp-templates/project.php        2010-04-09 15:23:52 UTC (rev 466)
</span><span class="lines">@@ -75,8 +75,9 @@
</span><span class="cx">         <p class="secondary actionlist">
</span><span class="cx">                 <?php gp_link( gp_url_project( $project, 'import-originals' ), __( 'Import originals' ) ); ?> &bull;
</span><span class="cx">                 <?php gp_link( gp_url_project( $project, array( '-permissions' ) ), __('Permissions') ); ?> &bull;
</span><del>-                <?php gp_link( gp_url_project( '', '-new', array('parent_project_id' => $project->id) ), __('Create a New Sub-Project') ); ?> &bull;
-                <?php gp_link( gp_url( '/sets/-new', array( 'project_id' => $project->id ) ), __('Create a New Translation Set') ); ?>
</del><ins>+                <?php gp_link( gp_url_project( '', '-new', array('parent_project_id' => $project->id) ), __('New Sub-Project') ); ?> &bull;
+                <?php gp_link( gp_url( '/sets/-new', array( 'project_id' => $project->id ) ), __('New Translation Set') ); ?> &bull;
+                <?php gp_link( gp_url_project( $project, array( '-mass-create-sets' ) ), __('Mass-create Translation Sets') ); ?>
</ins><span class="cx">         </p>
</span><span class="cx"> <?php endif; ?>
</span><span class="cx"> <script type="text/javascript" charset="utf-8">
</span></span></pre></div>
<a id="trunkgptemplatestranslationsetformphp"></a>
<div class="modfile"><h4>Modified: trunk/gp-templates/translation-set-form.php (465 => 466)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-templates/translation-set-form.php        2010-04-08 14:23:31 UTC (rev 465)
+++ trunk/gp-templates/translation-set-form.php        2010-04-09 15:23:52 UTC (rev 466)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> <dl>
</span><span class="cx">         <dt><label for="set[locale]"><?php _e('Locale'); ?></label></dt>
</span><span class="cx">         <dd>
</span><del>-                <?php echo gp_select( 'set[locale]', $all_locale_options, $set->locale); ?>
</del><ins>+                <?php echo gp_locales_dropdown( 'set[locale]', $set->locale ); ?>
</ins><span class="cx">                 <a href="#" id="copy"><?php _e('Use as name'); ?></a>
</span><span class="cx">         </dd>
</span><span class="cx">         
</span><span class="lines">@@ -13,15 +13,13 @@
</span><span class="cx">         <dd><input type="text" name="set[slug]" value="<?php echo esc_html( $set->slug? $set->slug : 'default' ); ?>" id="set[slug]"></dd>
</span><span class="cx">
</span><span class="cx">         <dt><label for="set[project_id]"><?php _e('Project'); ?></label></dt>
</span><del>-        <dd><?php echo gp_select( 'set[project_id]', $all_project_options, $set->project_id); ?></dd>
-        
-        
</del><ins>+        <dd><?php echo gp_projects_dropdown( 'set[project_id]', $set->project_id ); ?></dd>
</ins><span class="cx"> </dl>
</span><span class="cx"> <?php echo gp_js_focus_on( 'set[locale]' ); ?>
</span><span class="cx"> <script type="text/javascript">
</span><span class="cx">         jQuery(function($){
</span><span class="cx">                 $('#copy').click(function() {
</span><del>-                        $('#set\\[name\\]').val($('#set\\[locale\\] option:selected').html().replace(/^\S+\s+\S+\s+/, ''));
</del><ins>+                        $('#set\\[name\\]').val($('#set\\[locale\\] option:selected').html().replace(/^\S+\s+\S+\s+/, '').replace(/&mdash|—/, ''));
</ins><span class="cx">                         return false;
</span><span class="cx">                 });
</span><span class="cx">         });
</span></span></pre></div>
<a id="trunkjscommonjs"></a>
<div class="modfile"><h4>Modified: trunk/js/common.js (465 => 466)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/js/common.js        2010-04-08 14:23:31 UTC (rev 465)
+++ trunk/js/common.js        2010-04-09 15:23:52 UTC (rev 466)
</span><span class="lines">@@ -28,12 +28,14 @@
</span><span class="cx">                         $gp.notices.element.css('left', ($(document).width() - $gp.notices.element.width()) / 2);
</span><span class="cx">                 }
</span><span class="cx">         },
</span><ins>+        esc_html: function(s) {
+                return $('<div/>').text(s).html();
+        },
</ins><span class="cx">         init: function() {
</span><span class="cx">                 $gp.notices.init();
</span><span class="cx">         }
</span><span class="cx"> }}(jQuery);
</span><span class="cx">
</span><del>-
</del><span class="cx"> $gp.showhide = function($) { return function(link, show_text, hide_text, container, focus) {
</span><span class="cx">         link = $(link);
</span><span class="cx">         container = $(container);
</span></span></pre></div>
<a id="trunkjsmasscreatesetspagejs"></a>
<div class="addfile"><h4>Added: trunk/js/mass-create-sets-page.js (0 => 466)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/js/mass-create-sets-page.js         (rev 0)
+++ trunk/js/mass-create-sets-page.js        2010-04-09 15:23:52 UTC (rev 466)
</span><span class="lines">@@ -0,0 +1,51 @@
</span><ins>+jQuery(function($) {
+        $gp.notices.init();
+        $('#project_id').change(function() {
+                var select = $(this);
+                var project_id = $('option:selected', select).attr('value');
+                if ( !project_id ) {
+                        $('#submit').attr('disabled', 'disabled');
+                        $('#preview').hide();
+                        return;
+                }
+                $gp.notices.notice($gp_mass_create_sets_options.loading);
+                select.attr('disabled', 'disabled');
+                $.ajax({type: "POST", url: $gp_mass_create_sets_options.url, data: {project_id: project_id}, dataType: 'json',
+                        success: function(data){
+                                select.attr('disabled', '');
+                                $gp.notices.clear();
+                                if (data.added.length || data.removed.length) $('#submit').attr('disabled', '');
+                                var preview = $('#preview');
+                                preview.html('<h3>Preview changes:</h3>');
+                                var preview_html = '';
+                                preview_html += '<ul>';
+                                function preview_html_for(kind, text) {
+                                        var sets = data[kind];
+                                        var html = '';                                        
+                                        html += '<li><span class="'+kind+'">'+text.replace('{count}', sets.length)+'</span>';
+                                        if (sets.length) {
+                                                html += '<ul>';
+                                                $.each(sets, function() {
+                                                        html += '<li>'+$gp.esc_html(this.name)+' ('+this.locale+'/'+this.slug+')</li>';
+                                                });
+                                                html += '</ul>';
+                                        }
+                                        html += '</li>';
+                                        return html;
+                                }
+                                preview_html += preview_html_for('added', '{count} set(s) will be added');
+                                preview_html += preview_html_for('removed', '{count} set(s) will be removed');
+                                preview_html += '</ul>';
+                                preview.append(preview_html);
+                                preview.fadeIn();
+                        },
+                        error: function(xhr, msg, error) {
+                                select.attr('disabled', '');
+                                msg = xhr.responsehtml? 'Error: '+ xhr.responsehtml : 'Error saving the translation!';
+                                $gp.notices.error(msg);
+                        }
+                });                
+        });
+        $('#submit').attr('disabled', 'disabled');
+        $('#preview').hide();
+});
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/js/mass-create-sets-page.js
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:eol-style
</span><span class="cx"> + native
</span></span></pre></div>
<a id="trunkjstranslationspagejs"></a>
<div class="modfile"><h4>Modified: trunk/js/translations-page.js (465 => 466)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/js/translations-page.js        2010-04-08 14:23:31 UTC (rev 465)
+++ trunk/js/translations-page.js        2010-04-09 15:23:52 UTC (rev 466)
</span><span class="lines">@@ -80,4 +80,4 @@
</span><span class="cx">                 window.location = url;
</span><span class="cx">                 return false;
</span><span class="cx">         });
</span><del>-});
</del><span class="cx">\ No newline at end of file
</span><ins>+});
</ins></span></pre></div>
<a id="trunkttest_miscphp"></a>
<div class="modfile"><h4>Modified: trunk/t/test_misc.php (465 => 466)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/t/test_misc.php        2010-04-08 14:23:31 UTC (rev 465)
+++ trunk/t/test_misc.php        2010-04-09 15:23:52 UTC (rev 466)
</span><span class="lines">@@ -31,4 +31,12 @@
</span><span class="cx">                 $this->assertEquals( array( array('baba', 'dyado') ), gp_array_zip( array('baba', 'boom'), array('dyado') ) );
</span><span class="cx">                 $this->assertEquals( array( array( array('baba'), 'dyado') ), gp_array_zip( array( array('baba'), 'boom'), array('dyado') ) );
</span><span class="cx">         }
</span><ins>+        
+        function test_gp_array_any() {
+                $this->assertEquals( false, gp_array_any( 'intval', array( 0 ) ) );
+                $this->assertEquals( false, gp_array_any( returner(false), array( 1, 2, 3, 4 ) ) );
+                $this->assertEquals( false, gp_array_any( returner(true), array() ) );
+                $this->assertEquals( true, gp_array_any( returner(true), array( 1, 2, 3, 4 ) ) );
+                $this->assertEquals( true, gp_array_any( returner('$x', '$x % 2'), array( 1, 2, 3, 4 ) ) );
+        }
</ins><span class="cx"> }
</span><span class="cx">\ No newline at end of file
</span></span></pre>
</div>
</div>
</body>
</html>