launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #03227
[Merge] lp:~abentley/launchpad/js-translation-2 into lp:launchpad
Aaron Bentley has proposed merging lp:~abentley/launchpad/js-translation-2 into lp:launchpad with lp:~abentley/launchpad/json-init as a prerequisite.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~abentley/launchpad/js-translation-2/+merge/56648
= Summary =
Ajaxify productseries and automatic imports on +sharing-details.
This is the second of three branches.
== Pre-implementation notes ==
None
== Implementation details ==
Extracted IOHandler from select_branch and reused it for setting productseries
and autoimport.
Implement visible_check_selector so that the correct version of the checklist
item flashes on success or failure.
Revise update so that it works on all items in tsconfig.all_items. If all
entries in tsconfig.all_items are complete, set the "configuration" to
complete.
Provide replace_product and replace_productseries to handle all implications of
changing the product and productseries.
Handle "412 Precondition Failed" responses more clearly.
== Tests ==
bin/test --layer=WindmillLayer sharing_details
firefox lib/lp/translations/javascript/tests/test_sourcepackage_sharing_details.html
== Demo and Q/A ==
Go to a +sharing-details page and set the productseries and autoimports.
= Launchpad lint =
Checking for conflicts and issues in changed files.
Linting changed files:
lib/lp/testing/windmill/widgets.py
lib/lp/app/javascript/lp.js
lib/lp/translations/templates/sourcepackage-sharing-details.pt
lib/lp/app/javascript/client.js
lib/lp/translations/javascript/tests/test_sourcepackage_sharing_details.js
lib/lp/app/javascript/picker.js
lib/lp/translations/browser/tests/test_sharing_details.py
lib/lp/translations/windmill/tests/test_sourcepackage_sharing_details.py
lib/lp/translations/javascript/sourcepackage_sharing_details.js
lib/lp/translations/javascript/tests/test_sourcepackage_sharing_details.html
lib/lp/translations/browser/sourcepackage.py
./lib/lp/testing/windmill/widgets.py
29: E501 line too long (80 characters)
35: E501 line too long (80 characters)
36: E501 line too long (81 characters)
95: E501 line too long (83 characters)
122: E301 expected 1 blank line, found 0
27: Line exceeds 78 characters.
29: Line exceeds 78 characters.
35: Line exceeds 78 characters.
36: Line exceeds 78 characters.
43: Line exceeds 78 characters.
95: Line exceeds 78 characters.
./lib/lp/app/javascript/lp.js
53: Expected '!==' and instead saw '!='.
117: Expected '!==' and instead saw '!='.
187: Expected '===' and instead saw '=='.
290: Expected '===' and instead saw '=='.
305: Expected '===' and instead saw '=='.
306: Expected '===' and instead saw '=='.
338: Move 'var' declarations to the top of the function.
338: Stopping. (76% scanned).
0: JSLINT had a fatal error.
./lib/lp/app/javascript/client.js
30: Expected '===' and instead saw '=='.
33: Expected '===' and instead saw '=='.
54: Move 'var' declarations to the top of the function.
54: Stopping. (5% scanned).
0: JSLINT had a fatal error.
4: Line exceeds 78 characters.
191: Line exceeds 78 characters.
570: Line exceeds 78 characters.
618: Line exceeds 78 characters.
745: Line exceeds 78 characters.
747: Line exceeds 78 characters.
./lib/lp/app/javascript/picker.js
43: Expected ';' and instead saw 'if'.
92: Expected '!==' and instead saw '!='.
223: Expected '!==' and instead saw '!='.
224: Expected '{' and instead saw 'temp_spinner'.
257: Expected '!==' and instead saw '!='.
270: 'header' used out of scope.
271: 'step_title' used out of scope.
319: Move 'var' declarations to the top of the function.
319: Stopping. (85% scanned).
0: JSLINT had a fatal error.
194: Line exceeds 78 characters.
--
https://code.launchpad.net/~abentley/launchpad/js-translation-2/+merge/56648
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~abentley/launchpad/js-translation-2 into lp:launchpad.
=== modified file 'lib/lp/app/javascript/client.js'
--- lib/lp/app/javascript/client.js 2011-04-06 20:37:30 +0000
+++ lib/lp/app/javascript/client.js 2011-04-06 20:37:31 +0000
@@ -748,6 +748,8 @@
}
self.showError(server_error);
// Otherwise we send some sane text as an error
+ } else if (o.status == 412){
+ self.showError(o.status + ' ' + o.statusText);
} else {
self.showError(o.responseText);
}
=== modified file 'lib/lp/app/javascript/lp.js'
--- lib/lp/app/javascript/lp.js 2011-03-24 15:31:53 +0000
+++ lib/lp/app/javascript/lp.js 2011-04-06 20:37:31 +0000
@@ -262,7 +262,9 @@
});
});
};
-
+ Y.lp.get_url_path = function(url) {
+ return Y.Node.create('<a>junk</a>').set('href', url).get('pathname');
+ };
}, "0.1", {"requires":["cookie", "lazr.effects"]});
=== modified file 'lib/lp/app/javascript/picker.js'
--- lib/lp/app/javascript/picker.js 2011-04-06 20:37:30 +0000
+++ lib/lp/app/javascript/picker.js 2011-04-06 20:37:31 +0000
@@ -5,10 +5,6 @@
var BATCH_SIZE = 6;
var MAX_BATCHES = 20;
-function get_pathname(url) {
- return Y.Node.create('<a>junk</a>').set('href', url).get('pathname');
-}
-
/* Add a picker widget which will PATCH a given attribute on
* a given resource.
*
@@ -344,7 +340,7 @@
var uri = '';
if (Y.Lang.isValue(config['context'])){
- uri += get_pathname(config['context'].get('web_link')) + '/';
+ uri += Y.lp.get_url_path(config['context'].get('web_link')) + '/';
}
uri += '@@+huge-vocabulary?' + qs;
=== modified file 'lib/lp/testing/windmill/widgets.py'
--- lib/lp/testing/windmill/widgets.py 2011-03-29 07:10:40 +0000
+++ lib/lp/testing/windmill/widgets.py 2011-04-06 20:37:31 +0000
@@ -85,14 +85,15 @@
"""
super(SearchPickerWidget, self).__init__(client, 'yui3-picker')
self.search_input_xpath = (
- self.xpath + "//input[@class='yui3-picker-search']")
+ self.visible_xpath + "//input[@class='yui3-picker-search']")
self.search_button_xpath = (
- self.xpath + "//div[@class='yui3-picker-search-box']/button")
+ self.visible_xpath +
+ "//div[@class='yui3-picker-search-box']/button")
def _get_result_xpath_by_number(self, item_number):
"""Return the XPath for the given search result number."""
item_xpath = "//ul[@class='yui3-picker-results']/li[%d]/span" % item_number
- return self.xpath + item_xpath
+ return self.visible_xpath + item_xpath
def do_search(self, text):
"""Enter some text in the search field and click the search button.
=== modified file 'lib/lp/translations/javascript/sourcepackage_sharing_details.js'
--- lib/lp/translations/javascript/sourcepackage_sharing_details.js 2011-04-06 20:37:30 +0000
+++ lib/lp/translations/javascript/sourcepackage_sharing_details.js 2011-04-06 20:37:31 +0000
@@ -70,6 +70,10 @@
set_link: function(text, url){
this.set('_text', text);
this.set('_url', url);
+ },
+ clear_link: function(){
+ this.set('_text', null);
+ this.set('_url', null);
}
});
@@ -115,22 +119,76 @@
Y.extend(TranslationSharingConfig, Y.Base, {
initializer: function(){
var product_series = new LinkCheckItem(
- {identifier: 'product-series'});
+ {identifier: 'packaging'});
this.set('product_series', product_series);
var usage = new CheckItem(
- {identifier: 'usage', dependency: product_series});
+ {identifier: 'translation', dependency: product_series});
this.set('translations_usage', usage);
var branch = new LinkCheckItem(
{identifier: 'branch', dependency: this.get('product_series')});
this.set('branch', branch);
var autoimport = new CheckItem(
- {identifier: 'autoimport', dependency: branch});
+ {identifier: 'upstream-sync', dependency: branch});
this.set('autoimport', autoimport);
- this.set('all_items', [product_series, usage, branch, autoimport]);
+ var configuration = new CheckItem(
+ {identifier: 'configuration'});
+ this.set('configuration', configuration);
+ this.set(
+ 'all_items', [product_series, usage, branch, autoimport]);
}
});
namespace.TranslationSharingConfig = TranslationSharingConfig;
+
+function IOHandler(flash_target){
+ that = this;
+ this.flash_target = flash_target;
+ this.error_handler = new Y.lp.client.ErrorHandler();
+ this.error_handler.showError = function(error_msg) {
+ Y.lp.app.errors.display_error(Y.one(that.flash_target), error_msg);
+ };
+}
+
+
+/**
+ * Return an LP client config using error_handler.
+ *
+ * @param next {Object} A callback to call on success.
+ */
+IOHandler.prototype.get_config = function(next){
+ var config = {
+ on:{
+ success: next,
+ failure: this.error_handler.getFailureHandler()
+ }
+ };
+ return config;
+};
+
+
+/**
+ * Return an LP client config that will call the specified callbacks
+ * in sequence, using error_handler.
+ *
+ * @param next {Object} A callback to call on success.
+ */
+IOHandler.prototype.chain_config = function(){
+ var last_config;
+ var i;
+ // Each callback is bound to the next, so we use reverse order.
+ for(i = arguments.length-1; i >= 0; i--){
+ if (i === arguments.length - 1) {
+ callback = arguments[i];
+ }
+ else {
+ callback = Y.bind(arguments[i], this, last_config);
+ }
+ last_config = this.get_config(callback);
+ }
+ return last_config;
+};
+
+
/**
* This class is the controller for updating the TranslationSharingConfig.
* It handles updating the HTML and the DB model.
@@ -141,10 +199,11 @@
}
Y.extend(TranslationSharingController, Y.Base, {
initializer: function(source_package){
- this.set('source_package', source_package);
this.set('tsconfig', new TranslationSharingConfig());
this.set('productseries', null);
this.set('branch', null);
+ this.set('source_package', null);
+ this.set('branch_picker_config', null);
},
/*
* Select the specified branch as the translation branch.
@@ -152,18 +211,12 @@
* @param branch_summary {Object} An object containing api_url, css,
* description, value, title
*/
- configure: function(config){
- this.set_productseries(config.productseries);
- var autoimport_mode = namespace.autoimport_modes.no_import;
- var translations_usage = namespace.usage.unknown;
- if (!Y.Lang.isNull(config.productseries)){
- autoimport_mode = config.productseries.get(
- 'translations_autoimport_mode');
- translations_usage = config.product.get(
- 'translations_usage');
- }
- this.set_autoimport_mode(autoimport_mode);
- this.set_translations_usage(translations_usage);
+ configure: function(config, branch_picker_config, import_overlay){
+ this.set('branch_picker_config', branch_picker_config);
+ this.set('source_package', config.context);
+ this.set('import_overlay', import_overlay);
+ this.replace_productseries(config.productseries);
+ this.replace_product(config.product);
this.set_branch(config.upstream_branch);
},
set_productseries: function(productseries) {
@@ -173,15 +226,43 @@
productseries.get('title'), productseries.get('web_link'));
}
},
+ replace_productseries: function(productseries) {
+ this.set_productseries(productseries);
+ var autoimport_mode = namespace.autoimport_modes.no_import;
+ if (!Y.Lang.isNull(productseries)){
+ autoimport_mode = productseries.get(
+ 'translations_autoimport_mode');
+ var import_url = productseries.get('web_link');
+ import_url = Y.lp.get_url_path(import_url);
+ import_url += '/+translations-settings/++form++';
+ var import_overlay = this.get('import_overlay');
+ import_overlay.loadFormContentAndRender(import_url);
+ import_overlay.render();
+ }
+ this.set_autoimport_mode(autoimport_mode);
+ },
+ replace_product: function(product){
+ this.get('branch_picker_config').context = product;
+ var translations_usage = namespace.usage.unknown;
+ if (!Y.Lang.isNull(product)){
+ translations_usage = product.get('translations_usage');
+ }
+ this.set_translations_usage(translations_usage);
+ },
set_branch: function(branch){
this.set('branch', branch);
+ var check = this.get('tsconfig').get('branch');
if (Y.Lang.isValue(branch)){
- this.get('tsconfig').get('branch').set_link(
+ check.set_link(
branch.get('unique_name'), branch.get('web_link'));
}
+ else {
+ check.clear_link();
+ }
},
set_autoimport_mode: function(mode){
- complete = (mode === namespace.autoimport_modes.import_translations);
+ var complete = (
+ mode === namespace.autoimport_modes.import_translations);
this.get('tsconfig').get('autoimport').set('complete', complete);
},
set_translations_usage: function(usage){
@@ -191,48 +272,48 @@
var usage_check = this.get('tsconfig').get('translations_usage');
usage_check.set('complete', complete);
},
+ select_productseries: function(productseries_summary){
+ var that = this;
+ var productseries_check = that.get('tsconfig').get('product_series');
+ var lp_client = new Y.lp.client.Launchpad();
+ function save_productseries(config){
+ var source_package = that.get('source_package');
+ config.parameters = {
+ productseries: productseries_summary.api_uri};
+ source_package.named_post('setPackaging', config);
+ }
+ function get_productseries(config){
+ lp_client.get(productseries_summary.api_uri, config);
+ }
+ function cache_productseries(config, productseries){
+ that.replace_productseries(productseries);
+ var branch_link = productseries.get('branch_link');
+ if (branch_link === null){
+ config.on.success(null);
+ }
+ else {
+ lp_client.get(branch_link, config);
+ }
+ }
+ function cache_branch(config, branch){
+ that.set_branch(branch);
+ project_link = that.get('productseries').get('project_link');
+ lp_client.get(project_link, config);
+ }
+ function set_usage(product){
+ that.replace_product(product);
+ that.update();
+ that.flash_check_green(productseries_check);
+ }
+ var css_selector = this.visible_check_selector(productseries_check);
+ var io_handler = new IOHandler(css_selector);
+ save_productseries(io_handler.chain_config(
+ get_productseries, cache_productseries, cache_branch, set_usage));
+ },
select_branch: function(branch_summary){
var that = this;
var lp_client = new Y.lp.client.Launchpad();
- var error_handler = new Y.lp.client.ErrorHandler();
- error_handler.showError = function(error_msg) {
- Y.lp.app.errors.display_error(Y.one('#branch'), error_msg);
- };
- /**
- * Return an LP client config using error_handler.
- *
- * @param next {Object} A callback to call on success.
- */
- function get_config(next){
- var config = {
- on:{
- success: next,
- failure: error_handler.getFailureHandler()
- }
- };
- return config;
- }
- /**
- * Return an LP client config that will call the specified callbacks
- * in sequence, using error_handler.
- *
- * @param next {Object} A callback to call on success.
- */
- function chain_config(){
- var last_config;
- var i;
- // Each callback is bound to the next, so we use reverse order.
- for(i = arguments.length-1; i >= 0; i--){
- if (i === arguments.length - 1) {
- callback = arguments[i];
- }
- else {
- callback = Y.bind(arguments[i], this, last_config);
- }
- last_config = get_config(callback);
- }
- return last_config;
- }
+ var branch_check = that.get('tsconfig').get('branch');
/* Here begin a series of methods which each represent a step in
* setting the branch. They each take a config to use in an lp_client
@@ -253,36 +334,66 @@
function set_link(branch){
that.set_branch(branch);
that.update();
- var check = that.get('tsconfig').get('branch');
- var element = Y.one(that.check_selector(check, true));
- var anim = Y.lazr.anim.green_flash({node: element});
- anim.run();
+ that.flash_check_green(branch_check);
}
- save_branch(chain_config(get_branch, set_link));
+ css_selector = that.visible_check_selector(branch_check);
+ var io_handler = new IOHandler(css_selector);
+ save_branch(io_handler.chain_config(get_branch, set_link));
},
/**
* Update the display of all checklist items.
*/
update: function(){
- var branch = this.get('tsconfig').get('branch');
- this.update_check(branch);
+ var all_items = this.get('tsconfig').get('all_items');
+ var overall = this.get('tsconfig').get('configuration');
+ var i;
+ overall.set('complete', true);
+ for (i = 0; i < all_items.length; i++){
+ this.update_check(all_items[i]);
+ if (!all_items[i].get('complete')){
+ overall.set('complete', false);
+ }
+ }
+ this.update_check(overall);
},
check_selector: function(check, complete){
var completion = complete ? '-complete' : '-incomplete';
return '#' + check.get('identifier') + completion;
},
+ visible_check_selector: function(check){
+ return this.check_selector(check, check.get('complete'));
+ },
+ picker_selector: function(check, complete){
+ return this.check_selector(check, complete) + '-picker a';
+ },
/**
* Update the display of a single checklist item.
*/
update_check: function(check){
var complete = Y.one(this.check_selector(check, true));
- var link = complete.one('a.link');
- link.set('href', check.get('url'));
- link.set('text', check.get('text'));
+ var link = complete.one('.link a');
+ if (link !== null){
+ link.set('href', check.get('url'));
+ link.set('text', check.get('text'));
+ }
complete.toggleClass('unseen', !check.get('complete'));
+ complete.toggleClass('lowlight', !check.get('enabled'));
+ var complete_picker = Y.one(this.picker_selector(check, true));
+ if (complete_picker !== null) {
+ complete_picker.toggleClass('unseen', !check.get('enabled'));
+ }
var incomplete = Y.one(this.check_selector(check, false));
incomplete.toggleClass('unseen', check.get('complete'));
incomplete.toggleClass('lowlight', !check.get('enabled'));
+ var incomplete_picker = Y.one(this.picker_selector(check, false));
+ if (incomplete_picker !== null) {
+ incomplete_picker.toggleClass('unseen', !check.get('enabled'));
+ }
+ },
+ flash_check_green: function(check){
+ var element = Y.one(this.visible_check_selector(check));
+ var anim = Y.lazr.anim.green_flash({node: element});
+ anim.run();
}
});
namespace.TranslationSharingController = TranslationSharingController;
@@ -291,30 +402,77 @@
/**
* Method to prepare the AJAX translation sharing config functionality.
*/
-namespace.prepare = function(source_package, cache){
- var sharing_controller = new namespace.TranslationSharingController(
- source_package);
+namespace.prepare = function(cache){
+ var sharing_controller = new namespace.TranslationSharingController();
var lp_client = new Y.lp.client.Launchpad();
cache = namespace.convert_cache(lp_client, cache);
- sharing_controller.configure(cache);
- sharing_controller.update();
- var config = {
+ var branch_picker_config = {
picker_activator: '#branch-incomplete-picker a',
header : 'Select translation branch',
step_title: 'Search',
save: Y.bind('select_branch', sharing_controller),
context: cache.product
};
- var picker = Y.lp.app.picker.create('BranchRestrictedOnProduct', config);
- var element = Y.one('#branch-complete-picker a');
- /* Copy-pasted because picker can't normally be activated by two different
- * elements. */
- element.on('click', function(e) {
- e.halt();
- this.show();
- }, picker);
- element.addClass(picker.get('picker_activator_css_class'));
-
+ var picker = Y.lp.app.picker.create(
+ 'BranchRestrictedOnProduct', branch_picker_config);
+ function add_activator(picker, selector){
+ var element = Y.one(selector);
+ /* Copy-pasted because picker can't normally be activated by two
+ * different elements. */
+ element.on('click', function(e) {
+ e.halt();
+ this.show();
+ }, picker);
+ element.addClass(picker.get('picker_activator_css_class'));
+ }
+ add_activator(picker, '#branch-complete-picker a');
+ var productseries_picker_config = {
+ picker_activator: '#packaging-complete-picker a',
+ header : 'Select productseries',
+ step_title: 'Search',
+ save: Y.bind('select_productseries', sharing_controller),
+ context: cache.product
+ };
+ var productseries_picker = Y.lp.app.picker.create(
+ 'ProductSeries', productseries_picker_config);
+ add_activator(productseries_picker, '#packaging-incomplete-picker a');
+ var import_overlay = new Y.lazr.FormOverlay({
+ headerContent: '<h2>Import settings<h2>',
+ centered: true,
+ visible: false
+ });
+ import_overlay.set('form_submit_callback', function(form_data){
+ Y.log(form_data['field.translations_autoimport_mode']);
+ var key = form_data['field.translations_autoimport_mode'][0];
+ Y.log(key);
+ var mode = namespace.autoimport_modes[key.toLowerCase()];
+ Y.log(mode);
+ import_overlay.hide();
+ var product_series = sharing_controller.get('productseries');
+ product_series.set('translations_autoimport_mode', mode);
+ var autoimport_check = sharing_controller.get(
+ 'tsconfig').get('autoimport');
+ var css_selector = sharing_controller.visible_check_selector(
+ autoimport_check);
+ handler = new IOHandler(css_selector);
+ function update_controller(){
+ sharing_controller.set_autoimport_mode(mode);
+ sharing_controller.update();
+ sharing_controller.flash_check_green(autoimport_check);
+ }
+ /* XXX: AaronBentley 2011-04-04 bug=369293: Avoid 412 on repeated
+ * changes. This does not increase the risk of changing from a
+ * stale value, because the staleness check is not reasonable.
+ * The user is changing from the default shown in the form, not
+ * the value stored in productseries.
+ */
+ product_series.removeAttr('http_etag');
+ product_series.lp_save(handler.chain_config(update_controller));
+ });
+ add_activator(import_overlay, '#upstream-sync-complete-picker a');
+ add_activator(import_overlay, '#upstream-sync-incomplete-picker a');
+ sharing_controller.configure(cache, branch_picker_config, import_overlay);
+ sharing_controller.update();
};
-}, "0.1", {"requires": ['lp.app.errors', 'lp.app.picker', 'oop', 'lp.client']}
-);
+}, "0.1", {"requires": [
+ 'lp', 'lp.app.errors', 'lp.app.picker', 'oop', 'lp.client']});
=== modified file 'lib/lp/translations/javascript/tests/test_sourcepackage_sharing_details.html'
--- lib/lp/translations/javascript/tests/test_sourcepackage_sharing_details.html 2011-04-06 20:37:30 +0000
+++ lib/lp/translations/javascript/tests/test_sourcepackage_sharing_details.html 2011-04-06 20:37:31 +0000
@@ -14,6 +14,7 @@
<link rel="stylesheet"
href="../../../../canonical/launchpad/javascript/test.css" />
<script type="text/javascript" src="../../../app/javascript/client.js"></script>
+ <script type="text/javascript" src="../../../app/javascript/lp.js"></script>
<!-- The module under test -->
<script type="text/javascript" src="../sourcepackage_sharing_details.js"></script>
@@ -25,9 +26,45 @@
<!-- The example markup required by the script to run -->
<div id="expected-id">
- <div id="branch-complete">Branch selected: <a href="#" class="link"></a>
+ <div id="configuration-incomplete">
+ Translation sharing configuration is incomplete.
+ </div>
+ <div id="configuration-complete">
+ Translation sharing with upstream is active.
+ </div>
+ <div id="packaging-incomplete">
+ No upstream project series has been linked.
+ <a href="#picker" />
+ </div>
+ <div id="packaging-complete">
+ Linked upstream series is
+ <a href="#upstream-link" class="link">
+ Gimp trunk</a>.
+ <a href="#edit-link" ></a>
+ <a href="#remove-link" ></a>
+ </div>
+ <div id="branch-complete">Branch selected: <span class="link"><a
+ href="#" class="link"></a></span>
+ <span id="branch-complete-picker"><a href="#"></a></span>
</div>
<div id="branch-incomplete">No branch selected.</div>
+ <span id="branch-incomplete-picker"><a href="#"></a></span>
+ <div id="translation-incomplete">
+ Translations are not enabled on the upstream project.
+ <a href="#enable-translations"></a>
+ </div>
+ <div id="translation-complete">
+ Translations are enabled on the upstream project.
+ <a href="#enable-translations"></a>
+ </div>
+ <div id="upstream-sync-incomplete">
+ Automatic synchronization of translations is not enabled.
+ <a href="#enable-sync"></a>
+ </div>
+ <div id="upstream-sync-complete">
+ Automatic synchronization of translations is enabled.
+ <a href="#enable-sync"></a>
+ </div>
</div>
<!-- The test output -->
<div id="log"></div>
=== modified file 'lib/lp/translations/javascript/tests/test_sourcepackage_sharing_details.js'
--- lib/lp/translations/javascript/tests/test_sourcepackage_sharing_details.js 2011-04-06 20:37:30 +0000
+++ lib/lp/translations/javascript/tests/test_sourcepackage_sharing_details.js 2011-04-06 20:37:31 +0000
@@ -51,6 +51,13 @@
Y.Assert.areEqual('mytext', lci.get('text'));
Y.Assert.areEqual('http://example.com', lci.get('url'));
},
+ test_LinkCheckItem_clear: function() {
+ var lci = new LinkCheckItem();
+ lci.set_link('mytext', 'http://example.com');
+ lci.clear_link();
+ Y.Assert.isNull(lci.get('text'));
+ Y.Assert.isNull(lci.get('url'));
+ },
test_LinkCheckItem_complete: function() {
var lci = new LinkCheckItem();
Y.Assert.isFalse(lci.get('complete'));
@@ -73,12 +80,13 @@
Y.Assert.areEqual('id1', ci.get('identifier'));
},
test_configure_empty: function(){
- var ctrl = new TranslationSharingController({});
+ var ctrl = new TranslationSharingController();
var cache = {
productseries: null,
+ product: null,
upstream_branch: null
};
- ctrl.configure(cache);
+ ctrl.configure(cache, {});
},
test_configure: function(){
var cache = {
@@ -97,12 +105,19 @@
unique_name: 'title2',
web_link: 'http://web2',
resource_type_link: 'branch'
+ },
+ context: {
+ resource_type_link: 'http://sourcepackage'
}
};
- var ctrl = new TranslationSharingController({});
+ var ctrl = new TranslationSharingController();
var lp_client = new Y.lp.client.Launchpad();
cache = test_ns.convert_cache(lp_client, cache);
- ctrl.configure(cache);
+ var import_overlay = {
+ loadFormContentAndRender: function(){},
+ render: function(){}
+ };
+ ctrl.configure(cache, {}, import_overlay);
var tsconfig = ctrl.get('tsconfig');
Y.Assert.areEqual(
tsconfig.get('product_series').get('text'), 'title1');
@@ -113,6 +128,7 @@
Y.Assert.isTrue(tsconfig.get('autoimport').get('complete'));
Y.Assert.isTrue(
tsconfig.get('translations_usage').get('complete'));
+ Y.Assert.areSame(ctrl.get('source_package'), cache.context);
},
test_convert_cache: function(){
var cache = {
@@ -135,7 +151,7 @@
Y.Assert.areNotEqual('http:///', link.get('href'));
Y.Assert.isFalse(complete.hasClass('unseen'));
Y.Assert.isFalse(incomplete.hasClass('unseen'));
- var ctrl = new TranslationSharingController({});
+ var ctrl = new TranslationSharingController();
ctrl.update();
Y.Assert.isTrue(complete.hasClass('unseen'));
Y.Assert.isFalse(incomplete.hasClass('unseen'));
@@ -147,9 +163,32 @@
Y.Assert.areEqual('a', link.get('text'));
Y.Assert.areEqual('http:///', link.get('href'));
},
+ test_update_all: function(){
+ var ctrl = new TranslationSharingController();
+ var config = ctrl.get('tsconfig');
+ ctrl.update();
+ var config_incomplete = Y.one('#configuration-incomplete');
+ Y.Assert.isFalse(config_incomplete.hasClass('unseen'));
+ var pack_incomplete = Y.one('#packaging-incomplete');
+ Y.Assert.isFalse(pack_incomplete.hasClass('unseen'));
+ var usage_incomplete = Y.one('#translation-incomplete');
+ Y.Assert.isFalse(usage_incomplete.hasClass('unseen'));
+ var sync_incomplete = Y.one('#upstream-sync-incomplete');
+ Y.Assert.isFalse(sync_incomplete.hasClass('unseen'));
+ config.get('configuration').set('complete', true);
+ config.get('product_series').set_link('a', 'http:///');
+ config.get('branch').set_link('a', 'http:///');
+ config.get('translations_usage').set('complete', true);
+ config.get('autoimport').set('complete', true);
+ ctrl.update();
+ Y.Assert.isTrue(config_incomplete.hasClass('unseen'));
+ Y.Assert.isTrue(pack_incomplete.hasClass('unseen'));
+ Y.Assert.isTrue(usage_incomplete.hasClass('unseen'));
+ Y.Assert.isTrue(sync_incomplete.hasClass('unseen'));
+ },
test_update_check_disabled: function(){
var incomplete = Y.one('#branch-incomplete');
- var ctrl = new TranslationSharingController({});
+ var ctrl = new TranslationSharingController();
var branch = ctrl.get('tsconfig').get('branch');
ctrl.update_check(branch);
Y.Assert.isTrue(incomplete.hasClass('lowlight'));
@@ -159,7 +198,7 @@
Y.Assert.isFalse(incomplete.hasClass('lowlight'));
},
test_set_autoimport_mode: function(){
- var ctrl = new TranslationSharingController({});
+ var ctrl = new TranslationSharingController();
var check = ctrl.get('tsconfig').get('autoimport');
Y.Assert.isFalse(check.get('complete'));
ctrl.set_autoimport_mode('Import template and translation files');
@@ -168,7 +207,7 @@
Y.Assert.isFalse(check.get('complete'));
},
test_set_translations_usage: function(){
- var ctrl = new TranslationSharingController({});
+ var ctrl = new TranslationSharingController();
var check = ctrl.get('tsconfig').get('translations_usage');
ctrl.set_translations_usage('Unknown');
Y.Assert.isFalse(check.get('complete'));
=== modified file 'lib/lp/translations/templates/sourcepackage-sharing-details.pt'
--- lib/lp/translations/templates/sourcepackage-sharing-details.pt 2011-04-06 20:37:30 +0000
+++ lib/lp/translations/templates/sourcepackage-sharing-details.pt 2011-04-06 20:37:31 +0000
@@ -12,7 +12,7 @@
LPS.use('lp.translations.sourcepackage_sharing_details', function(Y) {
Y.on('domready', function() {
Y.lp.translations.sourcepackage_sharing_details.prepare(
- LP.cache['context'], LP.cache);
+ LP.cache);
});
});
</script>
@@ -36,14 +36,21 @@
<li tal:attributes="class view/packaging_incomplete_class"
id="packaging-incomplete">
No upstream project series has been linked.
- <a tal:replace="structure context/menu:overview/set_upstream/fmt:icon" />
+ <span id="packaging-incomplete-picker">
+ <a tal:replace="structure context/menu:overview/set_upstream/fmt:icon" />
+ </span>
</li>
<li tal:attributes="class view/packaging_complete_class"
id="packaging-complete">
Linked upstream series is
- <a tal:replace="structure context/productseries/fmt:link">
- Gimp trunk</a>.
- <a tal:replace="structure context/menu:overview/edit_packaging/fmt:icon" />
+ <span class="link">
+ <a tal:replace="structure context/productseries/fmt:link">
+ Gimp trunk</a>
+ <a tal:condition="not:context/productseries" href="#"></a>
+ </span>.
+ <span id="packaging-complete-picker">
+ <a tal:replace="structure context/menu:overview/edit_packaging/fmt:icon" />
+ </span>
<a tal:replace="structure context/menu:overview/remove_packaging/fmt:icon" />
</li>
<li tal:attributes="class view/branch_incomplete_class"
@@ -56,8 +63,10 @@
<li tal:attributes="class view/branch_complete_class"
id="branch-complete">
Upstream source branch is
+ <span class="link">
+ <a tal:replace="structure view/branch_link/escapedtext">lp:gimp</a>
+</span>
<span id="branch-complete-picker">
- <a tal:replace="structure view/branch_link/escapedtext">lp:gimp</a>
<a tal:replace="structure view/change_branch_link/escapedtext" />
</span>
</li>
@@ -68,18 +77,24 @@
</li>
<li tal:attributes="class view/translations_enabled_class"
id="translation-complete">
- Translations are enabled on the upstream project.
+ Translations are enabled on the upstream project.
+ <span id="translation-complete-picker">
<a tal:replace="structure view/configure_translations_link_configured/escapedtext" />
+ </span>
</li>
<li tal:attributes="class view/upstream_sync_disabled_class"
id="upstream-sync-incomplete">
Automatic synchronization of translations is not enabled.
+ <span id="upstream-sync-incomplete-picker">
<a tal:replace="structure view/translation_sync_link_unconfigured/escapedtext" />
+ </span>
</li>
<li tal:attributes="class view/upstream_sync_enabled_class"
id="upstream-sync-complete">
Automatic synchronization of translations is enabled.
+ <span id="upstream-sync-complete-picker">
<a tal:replace="structure view/translation_sync_link_configured/escapedtext" />
+ </span>
</li>
</ul>
</dd>
=== modified file 'lib/lp/translations/windmill/tests/test_sourcepackage_sharing_details.py'
--- lib/lp/translations/windmill/tests/test_sourcepackage_sharing_details.py 2011-04-06 20:37:30 +0000
+++ lib/lp/translations/windmill/tests/test_sourcepackage_sharing_details.py 2011-04-06 20:37:31 +0000
@@ -23,6 +23,9 @@
from lp.testing.windmill.widgets import (
search_and_select_picker_widget,
)
+from lp.translations.interfaces.translations import (
+ TranslationsBranchImportMode,
+)
from lp.translations.windmill.testing import (
TranslationsWindmillLayer,
)
@@ -33,22 +36,38 @@
layer = TranslationsWindmillLayer
def test_set_branch(self):
- packaging = self.factory.makePackagingLink()
+ sourcepackage = self.factory.makeSourcePackage()
+ productseries = self.factory.makeProductSeries(name='my-ps-name')
branch = self.factory.makeProductBranch(
- product=packaging.productseries.product, name='product-branch')
+ product=productseries.product, name='product-branch')
self.useContext(feature_flags())
set_feature_flag(u'translations.sharing_information.enabled', u'on')
transaction.commit()
-
client, start_url = self.getClientFor(
- packaging.sourcepackage, user=lpuser.TRANSLATIONS_ADMIN,
+ sourcepackage, user=lpuser.TRANSLATIONS_ADMIN,
view_name='+sharing-details')
client.waits.forElement(
id='branch-incomplete', timeout=FOR_ELEMENT)
+ client.click(xpath='//*[@id="packaging-incomplete-picker"]/a')
+ search_and_select_picker_widget(self.client, 'my-ps-name', 1)
+ client.waits.forElementProperty(
+ id='packaging-incomplete', option='className|sprite no unseen',
+ timeout=FOR_ELEMENT)
client.click(xpath='//*[@id="branch-incomplete-picker"]/a')
- search_and_select_picker_widget(client, 'product-branch', 1)
- client.waits.forElementProperty(
- id='branch-incomplete', option='className|sprite no unseen',
- timeout=FOR_ELEMENT)
+ search_and_select_picker_widget(self.client, 'product-branch', 1)
+ client.waits.forElementProperty(
+ xpath='//*[@id="upstream-sync-incomplete-picker"]/a',
+ option='className|sprite edit', timeout=FOR_ELEMENT)
+ client.click(
+ xpath='//*[@id="upstream-sync-incomplete-picker"]/a')
+ client.click(id='field.translations_autoimport_mode.2')
+ client.click(xpath='//input[@value="Submit"]')
+ client.waits.forElementProperty(
+ id='upstream-sync-incomplete',
+ option='className|sprite no unseen', timeout=FOR_ELEMENT)
transaction.commit()
- self.assertEqual(branch, packaging.productseries.branch)
+ self.assertEqual(sourcepackage.productseries, productseries)
+ self.assertEqual(branch, productseries.branch)
+ self.assertEqual(
+ TranslationsBranchImportMode.IMPORT_TRANSLATIONS,
+ productseries.translations_autoimport_mode)