From dba4d704af0f5240307124c960805f7dcfe1a931 Mon Sep 17 00:00:00 2001
From: rashmi73 <41687423+rashmi73@users.noreply.github.com>
Date: Sat, 30 Mar 2019 17:15:59 +0530
Subject: [PATCH 01/25] Update user.js
---
src/services/user.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/services/user.js b/src/services/user.js
index 13ec5948..7da7f53b 100644
--- a/src/services/user.js
+++ b/src/services/user.js
@@ -166,7 +166,8 @@ class User {
async getEmailPreferences(userId) {
const url = `/users/${userId}/preferences/email`;
const res = await this.private.api.get(url);
- return getApiResponsePayload(res);
+ const x = (await res.json()).result;
+ return x.content;
}
/**
From f20fe12b42aa009fb89c7d4d11854160b3b0e227 Mon Sep 17 00:00:00 2001
From: applehit16
\r\nOnce signed, you will be automatically added to the NDA terms of use and notified by email. \r\n
',agreed:!1,docusignTemplateId:"fake-template-id",serverInformation:{serverName:"TopCoder API",apiVersion:"0.0.1",requestDuration:4,currentTime:1504891122158},requesterInformation:{id:"d9994de712597c11d1caad64996d9fa0d9b4aa2c-w2VCwwGwnN6EeyhK",remoteIP:"12.34.56.789",receivedParams:{apiVersion:"v2",termsOfUseId:"21153",action:"getTermsOfUse"}}}},function(e){e.exports={terms:[{termsOfUseId:21193,title:"Standard Terms for Topcoder Competitions v2.1",url:"",agreeabilityType:"Electronically-agreeable",templateId:null},{termsOfUseId:21153,title:"Appirio NDA v2.0",url:"http://community.topcoder.com/tc?module=Terms&tuid=21153",agreeabilityType:"DocuSignable",templateId:"fake-template-id"}],serverInformation:{serverName:"Topcoder API",apiVersion:"0.0.1",requestDuration:11471,currentTime:1504879510947},requesterInformation:{id:"456f987dee6e9823179c8184fd3509ffdf9c613a-FyefLdEpb8UHgFQF",remoteIP:"12.34.567.890",receivedParams:{role:"Submitter",noauth:"true",apiVersion:"v2",challengeId:"30059255",action:"getChallengeTerms"}}}},function(e){e.exports={terms:[{termsOfUseId:21153,title:"Appirio NDA v2.0",url:"http://community.topcoder.com/tc?module=Terms&tuid=21153",agreeabilityType:"DocuSignable",agreed:!1,templateId:"fake-template-id"},{termsOfUseId:20704,title:"Standard Reviewer Terms v1.0",url:"",agreeabilityType:"Electronically-agreeable",agreed:!1,templateId:null}],serverInformation:{serverName:"Topcoder API",apiVersion:"0.0.1",requestDuration:29,currentTime:1504878884618},requesterInformation:{id:"1b37607c519c318194ce6da08c519c0a3f7c9855-7FSFCyd6oSX2mV6Z",remoteIP:"12.34.567.890",receivedParams:{role:"Submitter",apiVersion:"v2",challengeId:"30059255",action:"getChallengeTerms"}}}},function(e){e.exports={termsOfUseId:20704,title:"Standard Reviewer Terms v1.0",url:"",text:'THESE ARE THE TERMS AND CONDITIONS ("TERMS") UNDER WHICH YOU AGREE TO WORK UNDER AS A TOPCODER REVIEW BOARD MEMBER. THESE TERMS AND CONDITIONS AFFECT YOUR RIGHTS AND YOU SHOULD READ THEM CAREFULLY BEFORE AGREEING TO THEM. IN THESE TERMS AND CONDITIONS, "WE," "US," "ITS" AND "OUR" REFER TO TOPCODER, INC. AND "YOU" AND "YOUR" REFER TO YOU.
\r\n\r\nIt is understood that We need, and You have, expertise in evaluating and critiquing software designs and/or software development solutions. Furthermore, You agree that You are ready, willing, and able to undertake the performance of evaluating and critiquing such software designs and/or software development solutions submitted to Us, and You agree to assign and transfer your rights as a result of performing such services.
\r\n\r\nIn consideration of the premises and the mutual promises and covenants set forth herein, and for other good and valuable consideration, the receipt and sufficiency of which are hereby acknowledged, the parties agree as follows:
\r\n\r\nAs used in these Terms, the following capitalized terms shall have the following meanings unless otherwise indicated:
\r\n\r\n1.1.\t"Development(s)" shall mean any idea, design, concept, development, component, algorithm, process, method, formula, code, software, technique, technology, discovery or improvement, whether or not patentable, made, conceived, created, discovered, invented or reduced to practice by You in connection with the performance of services hereunder.
\r\n\r\n1.2.\t"Intellectual Property Rights" shall mean all intellectual property rights worldwide arising under statutory or common law or by contract and whether or not perfected, now existing or hereafter filed, issued or acquired, including all patent rights; all rights associated with works of authorship including copyrights and moral rights; rights relating to the protection of trade secrets and confidential information; and any right analogous to those set forth herein and any other proprietary rights relating to intangible property, other than Trademarks.
\r\n\r\n1.3.\t"TopCoder Information" shall mean TopCoder\'s and TopCoder Software\'s specifications, descriptions, architecture, plans, interfaces, and code for TopCoder\'s and TopCoder Software\'s hardware, software, and web site; TopCoder\'s competitions and competition operation procedures; TopCoder\'s and TopCoder Software\'s business and operational plans; and derivatives of the foregoing. The TopCoder Information shall be Confidential Information hereunder.
\r\n\r\n1.4.\t"Software Component" shall mean all software and related materials, technology and documentation (including without limitation design documents, source code and object code) to be evaluated and assessed by You for Us hereunder in accordance with our requirements, as set forth herein and in other documents provided by Us. The Software Component shall be Confidential Information hereunder.
\r\n\r\n2.1\tYou hereby agree to provide services relating to the evaluation and assessment of the Software Component. You agree to perform such services according to and in conformity with the following specifications, in addition to any specifications and/or scheduled provided by Us in our sole discretion (the "Services"):
\r\n\r\n2.2\tYou agree to commit sufficient time and resources to perform the Services according to the schedule set forth by Us. You shall promptly notify Us of any circumstances, as such circumstances arise, that may reasonably be anticipated to lead to a material deviation from the schedule.
\r\n\r\n2.3\tYou agree to keep Us updated, promptly upon our request, of any progress, problems, and/or developments of which You are aware regarding the Services. We shall have the right to require such updates in writing from You in a format specified by Us or acceptable to Us in our sole discretion. You shall conduct and conclude the Services in a professional manner.
\r\n\r\n3.1\tFee. In consideration for performance of the Services required by You, We shall pay You the fee set forth on TopCoder\'s website and/or in other correspondence from Us to You (the "Fee"). The Fee shall be in U.S. Dollars and may be paid in installments, as set forth on our website or in other correspondence from Us. The Fee shall be paid upon the conclusion of the review period, and once completed scorecards have been received, provided the completed scorecards are submitted to Us by the deadline as set forth on the website and/or in the correspondence from Us.
\r\n\r\n3.2\tRoyalty Payments.
\r\n \r\n(a)\tDefinitions. As used in this Section 3, the following capitalized terms shall have the following meanings unless otherwise indicated:
\r\n(b)\tIn consideration of Your evaluation of the Software Components and performance of Your obligations hereunder, We may pay to You a royalty (the "Royalty Payment"). The Royalty Payment to be paid shall be a portion of the Royalty Pool. The Royalty Pool shall be distributed as follows:
\r\n\r\n3.3\tTotal Payment. The sum of the Fee and the Royalty Payments shall be the total payment due to You. Any and all out-of-pocket expenses incurred by You in connection with performing the obligations hereunder are your sole responsibility. We will not reimburse You for any expenses incurred.
\r\n\r\n3.4\tYou shall not be entitled to receive any other compensation or any benefits from Us in connection with the Services. Except as otherwise required by law, We shall not withhold any sums or payments made to You for social security or other federal, state or local tax liabilities or contributions, and all withholdings, liabilities, and contributions shall be solely your responsibility. Further, You understand and agree that the Services are not covered under the unemployment compensation laws and are not intended to be covered by workers\' compensation laws.
\r\n\r\n4.1\tYou hereby acknowledge and agree that We own, solely and exclusively, all right, title and interest, including all Intellectual Property Rights, in and to the TopCoder Information. In addition, You hereby irrevocably and unconditionally transfer and assign to Us all right, title and interest You had, have, may have or acquire in or to all Developments and Software Components, and You agree to execute and deliver such documents, certificates, assignments and other writings, and take such other actions as may be necessary or desirable to vest in Us the ownership rights granted to Us hereunder.
\r\n\r\n4.2\tYou further agree that any and all works of authorship created, authored or developed by You hereunder shall be deemed to be "works made for hire" within the meaning of the United States Copyright Law and, as such, all rights therein including copyright shall belong solely and exclusively to Us from the time of their creation. To the extent any such work of authorship may not be deemed to be a work made for hire, You agree to, and do hereby, irrevocably and unconditionally transfer and assign to Us all right, title and interest including copyright in and to such work.
\r\n\r\n4.3\tYou agree that if We are unable, because of your unavailability, or for any other reason, to secure your signature to apply for or to pursue any application for any United States or foreign patents, mask work, copyright or trademark registrations covering the assignments to Us above, then You hereby irrevocably designates and appoints Us and your duly authorized officers and agents as your agent and attorney in fact, to act for and in your behalf and stead to execute and file any such applications and to do all other lawfully permitted acts to further the prosecution and issuance of patents, copyright, mask work and trademark registrations thereon with the same legal force and effect as if executed by your authorized agent.
\r\n\r\n4.4\tAll Intellectual Property Rights owned by a party as of the date You agree to these Terms shall remain the property of such party and no licenses or other rights with respect to such intellectual property are granted to the other party except as expressly set forth herein.
\r\n\r\n4.5\tNothing in these terms shall be construed as granting You any right or license under any of our Intellectual Property Right (including any rights We may have in any patents, copyrights, trademarks, service marks or any trade secrets), by implication, estoppel or otherwise, except as expressly set forth herein.
\r\n\r\n5.1\t"Confidential Information" shall mean any information, in whatever form, provided by Us to You with obligation of confidentiality, or designated by Us in writing as confidential, proprietary or marked with words of like import when provided to You, and information orally conveyed if We state at the time of oral conveyance or promptly thereafter that such information is confidential. Notwithstanding anything to the contrary contained herein, information about or relating to our software, our system interfaces, our hardware and software architecture, our business, operational and marketing plans, our member lists and database, all information and technology provided by Us to You to enable You to perform your obligations hereunder, TopCoder Information, and any and all Developments shall be considered Confidential Information.
\r\n\r\n5.2\tConfidential Information shall not include information which (a) was in your possession without confidentiality restriction prior to disclosure by Us hereunder; (b) at or after the time of disclosure by Us becomes generally available to the public through no act or omission on our part; (c) is developed by You independently of and without reference to any Confidential Information You receive from Us; or (d) has come into your possession without confidentiality restriction from a third party and such third party is under no obligation to Us to maintain the confidentiality of such information.
\r\n\r\n5.3\tYou acknowledge the confidential and proprietary nature of Confidential Information and agree (i) to hold Confidential Information in confidence and to take all reasonable precautions to protect such Confidential Information (including, without limitation, all precautions You employ with respect to your own confidential materials), (ii) not to divulge any such Confidential Information to any third person; and (iii) not to make any use whatsoever of such Confidential Information except as expressly authorized herein.
\r\n\r\n5.4\tIn the event You are ordered to disclose Confidential Information pursuant to a judicial or government request, requirement or order, You shall promptly notify Us and upon our request, You shall, at our expense, take reasonable steps to assist Us in contesting such request, requirement or order or in otherwise protecting our rights prior to disclosure.
\r\n\r\n5.5\tYou agree not to reproduce or copy by any means Confidential Information, except as reasonably required to perform the Services. Upon termination of your performance of the Services as a review board member, your right to use Confidential Information shall immediately terminate. In addition, upon such termination, or upon demand by Us at any time, You shall return promptly to Us or destroy, at our option, all tangible materials and computer data that disclose or embody Confidential Information.
\r\n\r\n5.6\tYou agree that any breach of these terms by You could cause irreparable damage to Us. In view of the difficulties of placing a monetary value on the Confidential Information, We shall have, in addition to any and all remedies of law, the right to an injunction or other equitable relief, and may be entitled to a preliminary and final injunction without the necessity of posting any bond or undertaking in connection therewith to prevent any further breach or further unauthorized use of Confidential Information. This remedy is separate from any other remedy We may have.
\r\n\r\n6.1\tYou represent and warrant that:\r\n
7.1\tYou shall indemnify, hold harmless and defend Us and our customers from and against any and all suits, actions, damages, costs, losses, expenses (including settlement awards and reasonable attorneys\' fees) and other liabilities arising from or in connection with any claim alleging that, to your knowledge, any Development and/or Software Component violates any trade secret right, or infringes any copyright, patent, trademark, or other intellectual property interest, in any country, and shall pay all costs and damages awarded. We shall promptly notify You of any such claim of which We are aware.
\r\n\r\n7.2\tYour obligations shall not extend to any claim for violation or infringement resulting solely from your compliance with any specific or direct written instructions from Us if such infringement would have been avoided but for such compliance.
\r\n\r\n8.1\tBoth parties expressly agree and understand that You are an independent contractor and nothing herein nor the services rendered hereunder is meant, or shall be construed in any way or manner, to create a relationship of employer and employee, principal and agent, partners or any other relationship other than that of independent parties contracting with each other solely for the purpose of carrying out the provisions of these Terms. Accordingly, You acknowledge and agree that You shall not be entitled to any benefits provided by Us to our employees. You shall be responsible for any and all out-of-pocket expenses incurred in connection with performing the Services. In addition, You shall have sole and exclusive responsibility for the payment of all federal, state and local income taxes, for all employment and disability insurance and for Social Security and other similar taxes with respect to any compensation provided by Us hereunder. You further agree that if We pay or become liable for such taxes or related civil penalties or interest as a result of your failure to pay taxes or report same, or due to our failure to withhold taxes, You shall indemnify and hold us harmless for any such liability. You shall assume and accept all responsibilities which are imposed on independent contractors by any statute, regulation, rule of law, or otherwise. You are not our agent and are not authorized and shall not have the power or authority to bind Us or incur any liability or obligation, or act on behalf of Us. At no time shall You represent that You are our agent, or that any of the views, advice, statements and/or information that may be provided while performing the Services are ours.
\r\n\r\n8.2\tWe are entitled to provide You with general guidance to assist You in completing the scope of work to our satisfaction, You are ultimately responsible for directing and controlling the performance of the task and the scope of work, in accordance with these Terms. You shall use your best efforts, energy and skill in your own name and in such manner as You see fit.
',agreeabilityType:"Electronically-agreeable",serverInformation:{serverName:"Topcoder API",apiVersion:"0.0.1",requestDuration:52,currentTime:1504892902498},requesterInformation:{id:"d8c441f8332161f71533f368c09aeead856e4366-K1RdFai7LCAgXVu5",remoteIP:"12.34.56.78",receivedParams:{apiVersion:"v2",termsOfUseId:"21193",action:"getTermsOfUse"}}}},function(e){e.exports={termsOfUseId:21193,title:"Standard Terms for Topcoder Competitions v2.1",url:"",agreeabilityType:"Electronically-agreeable",text:'\r\n\r\n\r\n\r\n\r\n\r\nBY E-MAIL: | \r\nGC@appirio.com | \r\n
BY MAIL: | \r\nDan Lascell\r\n\r\nTopcoder, Inc.\r\n\r\n760 Market Street\r\n\r\nSan Francisco, CA 94102 | \r\n
BY PHONE: | \r\n(650) 268-9911 | \r\n
\r\nOnce signed, you will be automatically added to the NDA terms of use and notified by email. \r\n
',agreed:!1,docusignTemplateId:"fake-template-id",serverInformation:{serverName:"TopCoder API",apiVersion:"0.0.1",requestDuration:4,currentTime:1504891122158},requesterInformation:{id:"d9994de712597c11d1caad64996d9fa0d9b4aa2c-w2VCwwGwnN6EeyhK",remoteIP:"12.34.56.789",receivedParams:{apiVersion:"v2",termsOfUseId:"21153",action:"getTermsOfUse"}}}},function(e){e.exports={terms:[{termsOfUseId:21193,title:"Standard Terms for Topcoder Competitions v2.1",url:"",agreeabilityType:"Electronically-agreeable",templateId:null},{termsOfUseId:21153,title:"Appirio NDA v2.0",url:"http://community.topcoder.com/tc?module=Terms&tuid=21153",agreeabilityType:"DocuSignable",templateId:"fake-template-id"}],serverInformation:{serverName:"Topcoder API",apiVersion:"0.0.1",requestDuration:11471,currentTime:1504879510947},requesterInformation:{id:"456f987dee6e9823179c8184fd3509ffdf9c613a-FyefLdEpb8UHgFQF",remoteIP:"12.34.567.890",receivedParams:{role:"Submitter",noauth:"true",apiVersion:"v2",challengeId:"30059255",action:"getChallengeTerms"}}}},function(e){e.exports={terms:[{termsOfUseId:21153,title:"Appirio NDA v2.0",url:"http://community.topcoder.com/tc?module=Terms&tuid=21153",agreeabilityType:"DocuSignable",agreed:!1,templateId:"fake-template-id"},{termsOfUseId:20704,title:"Standard Reviewer Terms v1.0",url:"",agreeabilityType:"Electronically-agreeable",agreed:!1,templateId:null}],serverInformation:{serverName:"Topcoder API",apiVersion:"0.0.1",requestDuration:29,currentTime:1504878884618},requesterInformation:{id:"1b37607c519c318194ce6da08c519c0a3f7c9855-7FSFCyd6oSX2mV6Z",remoteIP:"12.34.567.890",receivedParams:{role:"Submitter",apiVersion:"v2",challengeId:"30059255",action:"getChallengeTerms"}}}},function(e){e.exports={termsOfUseId:20704,title:"Standard Reviewer Terms v1.0",url:"",text:'THESE ARE THE TERMS AND CONDITIONS ("TERMS") UNDER WHICH YOU AGREE TO WORK UNDER AS A TOPCODER REVIEW BOARD MEMBER. THESE TERMS AND CONDITIONS AFFECT YOUR RIGHTS AND YOU SHOULD READ THEM CAREFULLY BEFORE AGREEING TO THEM. IN THESE TERMS AND CONDITIONS, "WE," "US," "ITS" AND "OUR" REFER TO TOPCODER, INC. AND "YOU" AND "YOUR" REFER TO YOU.
\r\n\r\nIt is understood that We need, and You have, expertise in evaluating and critiquing software designs and/or software development solutions. Furthermore, You agree that You are ready, willing, and able to undertake the performance of evaluating and critiquing such software designs and/or software development solutions submitted to Us, and You agree to assign and transfer your rights as a result of performing such services.
\r\n\r\nIn consideration of the premises and the mutual promises and covenants set forth herein, and for other good and valuable consideration, the receipt and sufficiency of which are hereby acknowledged, the parties agree as follows:
\r\n\r\nAs used in these Terms, the following capitalized terms shall have the following meanings unless otherwise indicated:
\r\n\r\n1.1.\t"Development(s)" shall mean any idea, design, concept, development, component, algorithm, process, method, formula, code, software, technique, technology, discovery or improvement, whether or not patentable, made, conceived, created, discovered, invented or reduced to practice by You in connection with the performance of services hereunder.
\r\n\r\n1.2.\t"Intellectual Property Rights" shall mean all intellectual property rights worldwide arising under statutory or common law or by contract and whether or not perfected, now existing or hereafter filed, issued or acquired, including all patent rights; all rights associated with works of authorship including copyrights and moral rights; rights relating to the protection of trade secrets and confidential information; and any right analogous to those set forth herein and any other proprietary rights relating to intangible property, other than Trademarks.
\r\n\r\n1.3.\t"TopCoder Information" shall mean TopCoder\'s and TopCoder Software\'s specifications, descriptions, architecture, plans, interfaces, and code for TopCoder\'s and TopCoder Software\'s hardware, software, and web site; TopCoder\'s competitions and competition operation procedures; TopCoder\'s and TopCoder Software\'s business and operational plans; and derivatives of the foregoing. The TopCoder Information shall be Confidential Information hereunder.
\r\n\r\n1.4.\t"Software Component" shall mean all software and related materials, technology and documentation (including without limitation design documents, source code and object code) to be evaluated and assessed by You for Us hereunder in accordance with our requirements, as set forth herein and in other documents provided by Us. The Software Component shall be Confidential Information hereunder.
\r\n\r\n2.1\tYou hereby agree to provide services relating to the evaluation and assessment of the Software Component. You agree to perform such services according to and in conformity with the following specifications, in addition to any specifications and/or scheduled provided by Us in our sole discretion (the "Services"):
\r\n\r\n2.2\tYou agree to commit sufficient time and resources to perform the Services according to the schedule set forth by Us. You shall promptly notify Us of any circumstances, as such circumstances arise, that may reasonably be anticipated to lead to a material deviation from the schedule.
\r\n\r\n2.3\tYou agree to keep Us updated, promptly upon our request, of any progress, problems, and/or developments of which You are aware regarding the Services. We shall have the right to require such updates in writing from You in a format specified by Us or acceptable to Us in our sole discretion. You shall conduct and conclude the Services in a professional manner.
\r\n\r\n3.1\tFee. In consideration for performance of the Services required by You, We shall pay You the fee set forth on TopCoder\'s website and/or in other correspondence from Us to You (the "Fee"). The Fee shall be in U.S. Dollars and may be paid in installments, as set forth on our website or in other correspondence from Us. The Fee shall be paid upon the conclusion of the review period, and once completed scorecards have been received, provided the completed scorecards are submitted to Us by the deadline as set forth on the website and/or in the correspondence from Us.
\r\n\r\n3.2\tRoyalty Payments.
\r\n \r\n(a)\tDefinitions. As used in this Section 3, the following capitalized terms shall have the following meanings unless otherwise indicated:
\r\n(b)\tIn consideration of Your evaluation of the Software Components and performance of Your obligations hereunder, We may pay to You a royalty (the "Royalty Payment"). The Royalty Payment to be paid shall be a portion of the Royalty Pool. The Royalty Pool shall be distributed as follows:
\r\n\r\n3.3\tTotal Payment. The sum of the Fee and the Royalty Payments shall be the total payment due to You. Any and all out-of-pocket expenses incurred by You in connection with performing the obligations hereunder are your sole responsibility. We will not reimburse You for any expenses incurred.
\r\n\r\n3.4\tYou shall not be entitled to receive any other compensation or any benefits from Us in connection with the Services. Except as otherwise required by law, We shall not withhold any sums or payments made to You for social security or other federal, state or local tax liabilities or contributions, and all withholdings, liabilities, and contributions shall be solely your responsibility. Further, You understand and agree that the Services are not covered under the unemployment compensation laws and are not intended to be covered by workers\' compensation laws.
\r\n\r\n4.1\tYou hereby acknowledge and agree that We own, solely and exclusively, all right, title and interest, including all Intellectual Property Rights, in and to the TopCoder Information. In addition, You hereby irrevocably and unconditionally transfer and assign to Us all right, title and interest You had, have, may have or acquire in or to all Developments and Software Components, and You agree to execute and deliver such documents, certificates, assignments and other writings, and take such other actions as may be necessary or desirable to vest in Us the ownership rights granted to Us hereunder.
\r\n\r\n4.2\tYou further agree that any and all works of authorship created, authored or developed by You hereunder shall be deemed to be "works made for hire" within the meaning of the United States Copyright Law and, as such, all rights therein including copyright shall belong solely and exclusively to Us from the time of their creation. To the extent any such work of authorship may not be deemed to be a work made for hire, You agree to, and do hereby, irrevocably and unconditionally transfer and assign to Us all right, title and interest including copyright in and to such work.
\r\n\r\n4.3\tYou agree that if We are unable, because of your unavailability, or for any other reason, to secure your signature to apply for or to pursue any application for any United States or foreign patents, mask work, copyright or trademark registrations covering the assignments to Us above, then You hereby irrevocably designates and appoints Us and your duly authorized officers and agents as your agent and attorney in fact, to act for and in your behalf and stead to execute and file any such applications and to do all other lawfully permitted acts to further the prosecution and issuance of patents, copyright, mask work and trademark registrations thereon with the same legal force and effect as if executed by your authorized agent.
\r\n\r\n4.4\tAll Intellectual Property Rights owned by a party as of the date You agree to these Terms shall remain the property of such party and no licenses or other rights with respect to such intellectual property are granted to the other party except as expressly set forth herein.
\r\n\r\n4.5\tNothing in these terms shall be construed as granting You any right or license under any of our Intellectual Property Right (including any rights We may have in any patents, copyrights, trademarks, service marks or any trade secrets), by implication, estoppel or otherwise, except as expressly set forth herein.
\r\n\r\n5.1\t"Confidential Information" shall mean any information, in whatever form, provided by Us to You with obligation of confidentiality, or designated by Us in writing as confidential, proprietary or marked with words of like import when provided to You, and information orally conveyed if We state at the time of oral conveyance or promptly thereafter that such information is confidential. Notwithstanding anything to the contrary contained herein, information about or relating to our software, our system interfaces, our hardware and software architecture, our business, operational and marketing plans, our member lists and database, all information and technology provided by Us to You to enable You to perform your obligations hereunder, TopCoder Information, and any and all Developments shall be considered Confidential Information.
\r\n\r\n5.2\tConfidential Information shall not include information which (a) was in your possession without confidentiality restriction prior to disclosure by Us hereunder; (b) at or after the time of disclosure by Us becomes generally available to the public through no act or omission on our part; (c) is developed by You independently of and without reference to any Confidential Information You receive from Us; or (d) has come into your possession without confidentiality restriction from a third party and such third party is under no obligation to Us to maintain the confidentiality of such information.
\r\n\r\n5.3\tYou acknowledge the confidential and proprietary nature of Confidential Information and agree (i) to hold Confidential Information in confidence and to take all reasonable precautions to protect such Confidential Information (including, without limitation, all precautions You employ with respect to your own confidential materials), (ii) not to divulge any such Confidential Information to any third person; and (iii) not to make any use whatsoever of such Confidential Information except as expressly authorized herein.
\r\n\r\n5.4\tIn the event You are ordered to disclose Confidential Information pursuant to a judicial or government request, requirement or order, You shall promptly notify Us and upon our request, You shall, at our expense, take reasonable steps to assist Us in contesting such request, requirement or order or in otherwise protecting our rights prior to disclosure.
\r\n\r\n5.5\tYou agree not to reproduce or copy by any means Confidential Information, except as reasonably required to perform the Services. Upon termination of your performance of the Services as a review board member, your right to use Confidential Information shall immediately terminate. In addition, upon such termination, or upon demand by Us at any time, You shall return promptly to Us or destroy, at our option, all tangible materials and computer data that disclose or embody Confidential Information.
\r\n\r\n5.6\tYou agree that any breach of these terms by You could cause irreparable damage to Us. In view of the difficulties of placing a monetary value on the Confidential Information, We shall have, in addition to any and all remedies of law, the right to an injunction or other equitable relief, and may be entitled to a preliminary and final injunction without the necessity of posting any bond or undertaking in connection therewith to prevent any further breach or further unauthorized use of Confidential Information. This remedy is separate from any other remedy We may have.
\r\n\r\n6.1\tYou represent and warrant that:\r\n
7.1\tYou shall indemnify, hold harmless and defend Us and our customers from and against any and all suits, actions, damages, costs, losses, expenses (including settlement awards and reasonable attorneys\' fees) and other liabilities arising from or in connection with any claim alleging that, to your knowledge, any Development and/or Software Component violates any trade secret right, or infringes any copyright, patent, trademark, or other intellectual property interest, in any country, and shall pay all costs and damages awarded. We shall promptly notify You of any such claim of which We are aware.
\r\n\r\n7.2\tYour obligations shall not extend to any claim for violation or infringement resulting solely from your compliance with any specific or direct written instructions from Us if such infringement would have been avoided but for such compliance.
\r\n\r\n8.1\tBoth parties expressly agree and understand that You are an independent contractor and nothing herein nor the services rendered hereunder is meant, or shall be construed in any way or manner, to create a relationship of employer and employee, principal and agent, partners or any other relationship other than that of independent parties contracting with each other solely for the purpose of carrying out the provisions of these Terms. Accordingly, You acknowledge and agree that You shall not be entitled to any benefits provided by Us to our employees. You shall be responsible for any and all out-of-pocket expenses incurred in connection with performing the Services. In addition, You shall have sole and exclusive responsibility for the payment of all federal, state and local income taxes, for all employment and disability insurance and for Social Security and other similar taxes with respect to any compensation provided by Us hereunder. You further agree that if We pay or become liable for such taxes or related civil penalties or interest as a result of your failure to pay taxes or report same, or due to our failure to withhold taxes, You shall indemnify and hold us harmless for any such liability. You shall assume and accept all responsibilities which are imposed on independent contractors by any statute, regulation, rule of law, or otherwise. You are not our agent and are not authorized and shall not have the power or authority to bind Us or incur any liability or obligation, or act on behalf of Us. At no time shall You represent that You are our agent, or that any of the views, advice, statements and/or information that may be provided while performing the Services are ours.
\r\n\r\n8.2\tWe are entitled to provide You with general guidance to assist You in completing the scope of work to our satisfaction, You are ultimately responsible for directing and controlling the performance of the task and the scope of work, in accordance with these Terms. You shall use your best efforts, energy and skill in your own name and in such manner as You see fit.
',agreeabilityType:"Electronically-agreeable",serverInformation:{serverName:"Topcoder API",apiVersion:"0.0.1",requestDuration:52,currentTime:1504892902498},requesterInformation:{id:"d8c441f8332161f71533f368c09aeead856e4366-K1RdFai7LCAgXVu5",remoteIP:"12.34.56.78",receivedParams:{apiVersion:"v2",termsOfUseId:"21193",action:"getTermsOfUse"}}}},function(e){e.exports={termsOfUseId:21193,title:"Standard Terms for Topcoder Competitions v2.1",url:"",agreeabilityType:"Electronically-agreeable",text:'\r\n\r\n\r\n\r\n\r\n\r\nBY E-MAIL: | \r\nGC@appirio.com | \r\n
BY MAIL: | \r\nDan Lascell\r\n\r\nTopcoder, Inc.\r\n\r\n760 Market Street\r\n\r\nSan Francisco, CA 94102 | \r\n
BY PHONE: | \r\n(650) 268-9911 | \r\n
Action
* [.getAchievementsInit(handle, uuid)](#module_actions.members.getAchievementsInit) ⇒ Action
* [.getAchievementsDone(handle, uuid)](#module_actions.members.getAchievementsDone) ⇒ Action
+ * [.getAchievementsV3Done(handle, uuid)](#module_actions.members.getAchievementsV3Done) ⇒ Action
* [.getFinancesInit(handle, uuid)](#module_actions.members.getFinancesInit) ⇒ Action
* [.getFinancesDone(handle, uuid, tokenV3)](#module_actions.members.getFinancesDone) ⇒ Action
* [.getStatsInit(handle, uuid)](#module_actions.members.getStatsInit) ⇒ Action
@@ -55,7 +56,19 @@ Creates an action that signals beginning of member achievements
### actions.members.getAchievementsDone(handle, uuid) ⇒ Action
-Creates an action that loads member achievements.
+Creates an action that loads member achievements from v2 API.
+
+**Kind**: static method of [actions.members
](#module_actions.members)
+
+| Param | Type | Description |
+| --- | --- | --- |
+| handle | String
| Member handle. |
+| uuid | String
| Loading operation |
+
+
+
+### actions.members.getAchievementsV3Done(handle, uuid) ⇒ Action
+Creates an action that loads member achievements from v3 API.
**Kind**: static method of [actions.members
](#module_actions.members)
diff --git a/docs/actions.profile.md b/docs/actions.profile.md
index 528d0612..9129918d 100644
--- a/docs/actions.profile.md
+++ b/docs/actions.profile.md
@@ -14,6 +14,7 @@ Actions for interactions with profile details API.
* [.clearProfile()](#module_actions.profile.clearProfile) ⇒ Action
* [.getAchievementsInit()](#module_actions.profile.getAchievementsInit) ⇒ Action
* [.getAchievementsDone(handle)](#module_actions.profile.getAchievementsDone) ⇒ Action
+ * [.getAchievementsV3Done(handle)](#module_actions.profile.getAchievementsV3Done) ⇒ Action
* [.getExternalAccountsInit()](#module_actions.profile.getExternalAccountsInit) ⇒ Action
* [.getExternalAccountsDone(handle)](#module_actions.profile.getExternalAccountsDone) ⇒ Action
* [.getExternalLinksInit()](#module_actions.profile.getExternalLinksInit) ⇒ Action
@@ -94,7 +95,7 @@ Creates an action that signals beginning of user achievements loading.
### actions.profile.getAchievementsDone(handle) ⇒ Action
-Creates an action that loads user achievements.
+Creates an action that loads user achievements from v2 API.
**Kind**: static method of [actions.profile
](#module_actions.profile)
**Todo**
@@ -106,6 +107,13 @@ Creates an action that loads user achievements.
| --- | --- | --- |
| handle | String
| User handle. |
+
+
+### actions.profile.getAchievementsV3Done(handle) ⇒ Action
+Creates an action that loads user achievements from V3 API.
+
+**Kind**: static method of [actions.profile
](#module_actions.profile)
+
### actions.profile.getExternalAccountsInit() ⇒ Action
diff --git a/docs/reducers.members.md b/docs/reducers.members.md
index 4d75fcfc..56811eb3 100644
--- a/docs/reducers.members.md
+++ b/docs/reducers.members.md
@@ -17,6 +17,7 @@ Reducer for the Redux store segment that holds members data.
* [~onDropAll()](#module_reducers.members..onDropAll) ⇒ Object
* [~onGetAchievementsInit(state)](#module_reducers.members..onGetAchievementsInit) ⇒ Object
* [~onGetAchievementsDone(state, error)](#module_reducers.members..onGetAchievementsDone) ⇒ Object
+ * [~onGetAchievementsV3Done(state, error)](#module_reducers.members..onGetAchievementsV3Done) ⇒ Object
* [~onGetFinancesInit(state)](#module_reducers.members..onGetFinancesInit) ⇒ Object
* [~onGetFinancesDone(state, action)](#module_reducers.members..onGetFinancesDone) ⇒ Object
* [~onGetStatsInit(state, action)](#module_reducers.members..onGetStatsInit) ⇒ Object
@@ -81,7 +82,23 @@ Inits the loading of member achievements.
### reducers.members~onGetAchievementsDone(state, error) ⇒ Object
-Finalizes the loading of member achievements.
+Finalizes the loading of member achievements from v2 API.
+
+**Kind**: inner method of [reducers.members
](#module_reducers.members)
+**Returns**: Object
- New state.
+
+| Param | Type |
+| --- | --- |
+| state | Object
|
+| error | Object
|
+| payload.data | Array
|
+| payload.handle | String
|
+| payload.uuid | String
|
+
+
+
+### reducers.members~onGetAchievementsV3Done(state, error) ⇒ Object
+Finalizes the loading of member achievements from v3 API.
**Kind**: inner method of [reducers.members
](#module_reducers.members)
**Returns**: Object
- New state.
diff --git a/docs/reducers.profile.md b/docs/reducers.profile.md
index 43d9ad78..21ae1d12 100644
--- a/docs/reducers.profile.md
+++ b/docs/reducers.profile.md
@@ -14,6 +14,7 @@ Actions for interactions with profile details API.
* [.clearProfile()](#module_actions.profile.clearProfile) ⇒ Action
* [.getAchievementsInit()](#module_actions.profile.getAchievementsInit) ⇒ Action
* [.getAchievementsDone(handle)](#module_actions.profile.getAchievementsDone) ⇒ Action
+ * [.getAchievementsV3Done(handle)](#module_actions.profile.getAchievementsV3Done) ⇒ Action
* [.getExternalAccountsInit()](#module_actions.profile.getExternalAccountsInit) ⇒ Action
* [.getExternalAccountsDone(handle)](#module_actions.profile.getExternalAccountsDone) ⇒ Action
* [.getExternalLinksInit()](#module_actions.profile.getExternalLinksInit) ⇒ Action
@@ -94,7 +95,22 @@ Creates an action that signals beginning of user achievements loading.
### actions.profile.getAchievementsDone(handle) ⇒ Action
-Creates an action that loads user achievements.
+Creates an action that loads user achievements from v2 API.
+
+**Kind**: static method of [actions.profile
](#module_actions.profile)
+**Todo**
+
+- [ ] This duplicates similar action in [actions.members.md](actions.members.md)!
+
+
+| Param | Type | Description |
+| --- | --- | --- |
+| handle | String
| User handle. |
+
+
+
+### actions.profile.getAchievementsV3Done(handle) ⇒ Action
+Creates an action that loads user achievements from v3 API.
**Kind**: static method of [actions.profile
](#module_actions.profile)
**Todo**
diff --git a/docs/services.user.md b/docs/services.user.md
index de282529..fc039b68 100644
--- a/docs/services.user.md
+++ b/docs/services.user.md
@@ -14,6 +14,7 @@ The User service provides functionality related to Topcoder user
* [new User(tokenV3, tokenV2)](#new_module_services.user..User_new)
* [.getAchievements(username)](#module_services.user..User+getAchievements) ⇒ Object
* [.getUserPublic(username)](#module_services.user..User+getUserPublic) ⇒ Object
+ * [.getUserPublicV3(username)](#module_services.user..User+getUserPublicV3) ⇒ Object
* [.getUser(username)](#module_services.user..User+getUser) ⇒ Promise
* [.getEmailPreferences(userId)](#module_services.user..User+getEmailPreferences) ⇒ Promise
* [.saveEmailPreferences(user, preferences)](#module_services.user..User+saveEmailPreferences) ⇒ Promise
@@ -54,6 +55,7 @@ Service class.
* [new User(tokenV3, tokenV2)](#new_module_services.user..User_new)
* [.getAchievements(username)](#module_services.user..User+getAchievements) ⇒ Object
* [.getUserPublic(username)](#module_services.user..User+getUserPublic) ⇒ Object
+ * [.getUserPublicV3(username)](#module_services.user..User+getUserPublicV3) ⇒ Object
* [.getUser(username)](#module_services.user..User+getUser) ⇒ Promise
* [.getEmailPreferences(userId)](#module_services.user..User+getEmailPreferences) ⇒ Promise
* [.saveEmailPreferences(user, preferences)](#module_services.user..User+saveEmailPreferences) ⇒ Promise
@@ -88,7 +90,18 @@ Gets user achievements. Does not need auth.
#### user.getUserPublic(username) ⇒ Object
-Gets public user info. Does not need auth.
+Gets public user info from v2 API. Does not need auth.
+
+**Kind**: instance method of [User
](#module_services.user..User)
+
+| Param | Type |
+| --- | --- |
+| username | String
|
+
+
+
+#### user.getUserPublicV3(username) ⇒ Object
+Gets public user info from v3 API. Does not need auth.
**Kind**: instance method of [User
](#module_services.user..User)
diff --git a/docs/tc.md b/docs/tc.md
index e1e92105..60a67427 100644
--- a/docs/tc.md
+++ b/docs/tc.md
@@ -11,6 +11,7 @@ Collection of small Topcoder-related functions.
* [tc](#module_tc)
* [.REVIEW_OPPORTUNITY_TYPES](#module_tc.REVIEW_OPPORTUNITY_TYPES)
* [.getApiResponsePayload(res)](#module_tc.getApiResponsePayload) ⇒ Promise
+ * [.getApiResponsePayloadV3(res)](#module_tc.getApiResponsePayloadV3) ⇒ Promise
@@ -21,7 +22,7 @@ Review Opportunity types
### tc.getApiResponsePayload(res) ⇒ Promise
-Gets payload from a standard success response from TC API; or throws
+Gets payload from a standard success response from TC v2 API; or throws
an error in case of a failure response.
**Kind**: static method of [tc
](#module_tc)
@@ -31,3 +32,15 @@ an error in case of a failure response.
| --- | --- |
| res | Object
|
+
+
+### tc.getApiResponsePayloadV3(res) ⇒ Promise
+Gets payload from a standard success response from TC v3 API; or throws
+an error in case of a failure response.
+
+**Kind**: static method of [tc
](#module_tc)
+**Returns**: Promise
- Resolves to the payload.
+
+| Param | Type |
+| --- | --- |
+| res | Object
|
From 99d378bb02f1675824f2bbd5b0e346b02d0d6468 Mon Sep 17 00:00:00 2001
From: Huan Li Promise
- * [.getApiResponsePayloadV3(res)](#module_tc.getApiResponsePayloadV3) ⇒ Promise
@@ -32,15 +31,3 @@ an error in case of a failure response.
| --- | --- |
| res | Object
|
-
-
-### tc.getApiResponsePayloadV3(res) ⇒ Promise
-Gets payload from a standard success response from TC v3 API; or throws
-an error in case of a failure response.
-
-**Kind**: static method of [tc
](#module_tc)
-**Returns**: Promise
- Resolves to the payload.
-
-| Param | Type |
-| --- | --- |
-| res | Object
|
diff --git a/src/services/user.js b/src/services/user.js
index ff1a780e..802f5af3 100644
--- a/src/services/user.js
+++ b/src/services/user.js
@@ -6,7 +6,7 @@
import { config, isomorphy } from 'topcoder-react-utils';
import logger from '../utils/logger';
-import { getApiResponsePayload, getApiResponsePayloadV3 } from '../utils/tc';
+import { getApiResponsePayload } from '../utils/tc';
import { getApi } from './api';
let auth0;
@@ -148,7 +148,7 @@ class User {
*/
async getUserPublicV3(username) {
const res = await this.private.api.get(`/members/${username}`);
- return getApiResponsePayloadV3(res);
+ return getApiResponsePayload(res);
}
/**
diff --git a/src/utils/tc.js b/src/utils/tc.js
index 3ea8a786..77fce85a 100644
--- a/src/utils/tc.js
+++ b/src/utils/tc.js
@@ -38,19 +38,6 @@ export async function getApiResponsePayload(res) {
return x.content;
}
-/**
- * Gets payload from a standard success response from TC API v3; or throws
- * an error in case of a failure response.
- * @param {Object} res
- * @return {Promise} Resolves to the payload.
- */
-export async function getApiResponsePayloadV3(res) {
- if (!res.ok) throw new Error(res.statusText);
- const x = (await res.json()).result;
- if (!x.success) throw new Error(x.content);
- return x.content;
-}
-
/**
* Gets payload from a standard success response from TC LOOKER API; or throws
* an error in case of a failure response.
From e1c8d7a330cf518caeaed101c7a3eb455fb4ab12 Mon Sep 17 00:00:00 2001
From: Huan Li \r\nOnce signed, you will be automatically added to the NDA terms of use and notified by email. \r\n
',agreed:!1,docusignTemplateId:"fake-template-id",serverInformation:{serverName:"TopCoder API",apiVersion:"0.0.1",requestDuration:4,currentTime:1504891122158},requesterInformation:{id:"d9994de712597c11d1caad64996d9fa0d9b4aa2c-w2VCwwGwnN6EeyhK",remoteIP:"12.34.56.789",receivedParams:{apiVersion:"v2",termsOfUseId:"21153",action:"getTermsOfUse"}}}},function(e){e.exports={terms:[{termsOfUseId:21193,title:"Standard Terms for Topcoder Competitions v2.1",url:"",agreeabilityType:"Electronically-agreeable",templateId:null},{termsOfUseId:21153,title:"Appirio NDA v2.0",url:"http://community.topcoder.com/tc?module=Terms&tuid=21153",agreeabilityType:"DocuSignable",templateId:"fake-template-id"}],serverInformation:{serverName:"Topcoder API",apiVersion:"0.0.1",requestDuration:11471,currentTime:1504879510947},requesterInformation:{id:"456f987dee6e9823179c8184fd3509ffdf9c613a-FyefLdEpb8UHgFQF",remoteIP:"12.34.567.890",receivedParams:{role:"Submitter",noauth:"true",apiVersion:"v2",challengeId:"30059255",action:"getChallengeTerms"}}}},function(e){e.exports={terms:[{termsOfUseId:21153,title:"Appirio NDA v2.0",url:"http://community.topcoder.com/tc?module=Terms&tuid=21153",agreeabilityType:"DocuSignable",agreed:!1,templateId:"fake-template-id"},{termsOfUseId:20704,title:"Standard Reviewer Terms v1.0",url:"",agreeabilityType:"Electronically-agreeable",agreed:!1,templateId:null}],serverInformation:{serverName:"Topcoder API",apiVersion:"0.0.1",requestDuration:29,currentTime:1504878884618},requesterInformation:{id:"1b37607c519c318194ce6da08c519c0a3f7c9855-7FSFCyd6oSX2mV6Z",remoteIP:"12.34.567.890",receivedParams:{role:"Submitter",apiVersion:"v2",challengeId:"30059255",action:"getChallengeTerms"}}}},function(e){e.exports={termsOfUseId:20704,title:"Standard Reviewer Terms v1.0",url:"",text:'THESE ARE THE TERMS AND CONDITIONS ("TERMS") UNDER WHICH YOU AGREE TO WORK UNDER AS A TOPCODER REVIEW BOARD MEMBER. THESE TERMS AND CONDITIONS AFFECT YOUR RIGHTS AND YOU SHOULD READ THEM CAREFULLY BEFORE AGREEING TO THEM. IN THESE TERMS AND CONDITIONS, "WE," "US," "ITS" AND "OUR" REFER TO TOPCODER, INC. AND "YOU" AND "YOUR" REFER TO YOU.
\r\n\r\nIt is understood that We need, and You have, expertise in evaluating and critiquing software designs and/or software development solutions. Furthermore, You agree that You are ready, willing, and able to undertake the performance of evaluating and critiquing such software designs and/or software development solutions submitted to Us, and You agree to assign and transfer your rights as a result of performing such services.
\r\n\r\nIn consideration of the premises and the mutual promises and covenants set forth herein, and for other good and valuable consideration, the receipt and sufficiency of which are hereby acknowledged, the parties agree as follows:
\r\n\r\nAs used in these Terms, the following capitalized terms shall have the following meanings unless otherwise indicated:
\r\n\r\n1.1.\t"Development(s)" shall mean any idea, design, concept, development, component, algorithm, process, method, formula, code, software, technique, technology, discovery or improvement, whether or not patentable, made, conceived, created, discovered, invented or reduced to practice by You in connection with the performance of services hereunder.
\r\n\r\n1.2.\t"Intellectual Property Rights" shall mean all intellectual property rights worldwide arising under statutory or common law or by contract and whether or not perfected, now existing or hereafter filed, issued or acquired, including all patent rights; all rights associated with works of authorship including copyrights and moral rights; rights relating to the protection of trade secrets and confidential information; and any right analogous to those set forth herein and any other proprietary rights relating to intangible property, other than Trademarks.
\r\n\r\n1.3.\t"TopCoder Information" shall mean TopCoder\'s and TopCoder Software\'s specifications, descriptions, architecture, plans, interfaces, and code for TopCoder\'s and TopCoder Software\'s hardware, software, and web site; TopCoder\'s competitions and competition operation procedures; TopCoder\'s and TopCoder Software\'s business and operational plans; and derivatives of the foregoing. The TopCoder Information shall be Confidential Information hereunder.
\r\n\r\n1.4.\t"Software Component" shall mean all software and related materials, technology and documentation (including without limitation design documents, source code and object code) to be evaluated and assessed by You for Us hereunder in accordance with our requirements, as set forth herein and in other documents provided by Us. The Software Component shall be Confidential Information hereunder.
\r\n\r\n2.1\tYou hereby agree to provide services relating to the evaluation and assessment of the Software Component. You agree to perform such services according to and in conformity with the following specifications, in addition to any specifications and/or scheduled provided by Us in our sole discretion (the "Services"):
\r\n\r\n2.2\tYou agree to commit sufficient time and resources to perform the Services according to the schedule set forth by Us. You shall promptly notify Us of any circumstances, as such circumstances arise, that may reasonably be anticipated to lead to a material deviation from the schedule.
\r\n\r\n2.3\tYou agree to keep Us updated, promptly upon our request, of any progress, problems, and/or developments of which You are aware regarding the Services. We shall have the right to require such updates in writing from You in a format specified by Us or acceptable to Us in our sole discretion. You shall conduct and conclude the Services in a professional manner.
\r\n\r\n3.1\tFee. In consideration for performance of the Services required by You, We shall pay You the fee set forth on TopCoder\'s website and/or in other correspondence from Us to You (the "Fee"). The Fee shall be in U.S. Dollars and may be paid in installments, as set forth on our website or in other correspondence from Us. The Fee shall be paid upon the conclusion of the review period, and once completed scorecards have been received, provided the completed scorecards are submitted to Us by the deadline as set forth on the website and/or in the correspondence from Us.
\r\n\r\n3.2\tRoyalty Payments.
\r\n \r\n(a)\tDefinitions. As used in this Section 3, the following capitalized terms shall have the following meanings unless otherwise indicated:
\r\n(b)\tIn consideration of Your evaluation of the Software Components and performance of Your obligations hereunder, We may pay to You a royalty (the "Royalty Payment"). The Royalty Payment to be paid shall be a portion of the Royalty Pool. The Royalty Pool shall be distributed as follows:
\r\n\r\n3.3\tTotal Payment. The sum of the Fee and the Royalty Payments shall be the total payment due to You. Any and all out-of-pocket expenses incurred by You in connection with performing the obligations hereunder are your sole responsibility. We will not reimburse You for any expenses incurred.
\r\n\r\n3.4\tYou shall not be entitled to receive any other compensation or any benefits from Us in connection with the Services. Except as otherwise required by law, We shall not withhold any sums or payments made to You for social security or other federal, state or local tax liabilities or contributions, and all withholdings, liabilities, and contributions shall be solely your responsibility. Further, You understand and agree that the Services are not covered under the unemployment compensation laws and are not intended to be covered by workers\' compensation laws.
\r\n\r\n4.1\tYou hereby acknowledge and agree that We own, solely and exclusively, all right, title and interest, including all Intellectual Property Rights, in and to the TopCoder Information. In addition, You hereby irrevocably and unconditionally transfer and assign to Us all right, title and interest You had, have, may have or acquire in or to all Developments and Software Components, and You agree to execute and deliver such documents, certificates, assignments and other writings, and take such other actions as may be necessary or desirable to vest in Us the ownership rights granted to Us hereunder.
\r\n\r\n4.2\tYou further agree that any and all works of authorship created, authored or developed by You hereunder shall be deemed to be "works made for hire" within the meaning of the United States Copyright Law and, as such, all rights therein including copyright shall belong solely and exclusively to Us from the time of their creation. To the extent any such work of authorship may not be deemed to be a work made for hire, You agree to, and do hereby, irrevocably and unconditionally transfer and assign to Us all right, title and interest including copyright in and to such work.
\r\n\r\n4.3\tYou agree that if We are unable, because of your unavailability, or for any other reason, to secure your signature to apply for or to pursue any application for any United States or foreign patents, mask work, copyright or trademark registrations covering the assignments to Us above, then You hereby irrevocably designates and appoints Us and your duly authorized officers and agents as your agent and attorney in fact, to act for and in your behalf and stead to execute and file any such applications and to do all other lawfully permitted acts to further the prosecution and issuance of patents, copyright, mask work and trademark registrations thereon with the same legal force and effect as if executed by your authorized agent.
\r\n\r\n4.4\tAll Intellectual Property Rights owned by a party as of the date You agree to these Terms shall remain the property of such party and no licenses or other rights with respect to such intellectual property are granted to the other party except as expressly set forth herein.
\r\n\r\n4.5\tNothing in these terms shall be construed as granting You any right or license under any of our Intellectual Property Right (including any rights We may have in any patents, copyrights, trademarks, service marks or any trade secrets), by implication, estoppel or otherwise, except as expressly set forth herein.
\r\n\r\n5.1\t"Confidential Information" shall mean any information, in whatever form, provided by Us to You with obligation of confidentiality, or designated by Us in writing as confidential, proprietary or marked with words of like import when provided to You, and information orally conveyed if We state at the time of oral conveyance or promptly thereafter that such information is confidential. Notwithstanding anything to the contrary contained herein, information about or relating to our software, our system interfaces, our hardware and software architecture, our business, operational and marketing plans, our member lists and database, all information and technology provided by Us to You to enable You to perform your obligations hereunder, TopCoder Information, and any and all Developments shall be considered Confidential Information.
\r\n\r\n5.2\tConfidential Information shall not include information which (a) was in your possession without confidentiality restriction prior to disclosure by Us hereunder; (b) at or after the time of disclosure by Us becomes generally available to the public through no act or omission on our part; (c) is developed by You independently of and without reference to any Confidential Information You receive from Us; or (d) has come into your possession without confidentiality restriction from a third party and such third party is under no obligation to Us to maintain the confidentiality of such information.
\r\n\r\n5.3\tYou acknowledge the confidential and proprietary nature of Confidential Information and agree (i) to hold Confidential Information in confidence and to take all reasonable precautions to protect such Confidential Information (including, without limitation, all precautions You employ with respect to your own confidential materials), (ii) not to divulge any such Confidential Information to any third person; and (iii) not to make any use whatsoever of such Confidential Information except as expressly authorized herein.
\r\n\r\n5.4\tIn the event You are ordered to disclose Confidential Information pursuant to a judicial or government request, requirement or order, You shall promptly notify Us and upon our request, You shall, at our expense, take reasonable steps to assist Us in contesting such request, requirement or order or in otherwise protecting our rights prior to disclosure.
\r\n\r\n5.5\tYou agree not to reproduce or copy by any means Confidential Information, except as reasonably required to perform the Services. Upon termination of your performance of the Services as a review board member, your right to use Confidential Information shall immediately terminate. In addition, upon such termination, or upon demand by Us at any time, You shall return promptly to Us or destroy, at our option, all tangible materials and computer data that disclose or embody Confidential Information.
\r\n\r\n5.6\tYou agree that any breach of these terms by You could cause irreparable damage to Us. In view of the difficulties of placing a monetary value on the Confidential Information, We shall have, in addition to any and all remedies of law, the right to an injunction or other equitable relief, and may be entitled to a preliminary and final injunction without the necessity of posting any bond or undertaking in connection therewith to prevent any further breach or further unauthorized use of Confidential Information. This remedy is separate from any other remedy We may have.
\r\n\r\n6.1\tYou represent and warrant that:\r\n
7.1\tYou shall indemnify, hold harmless and defend Us and our customers from and against any and all suits, actions, damages, costs, losses, expenses (including settlement awards and reasonable attorneys\' fees) and other liabilities arising from or in connection with any claim alleging that, to your knowledge, any Development and/or Software Component violates any trade secret right, or infringes any copyright, patent, trademark, or other intellectual property interest, in any country, and shall pay all costs and damages awarded. We shall promptly notify You of any such claim of which We are aware.
\r\n\r\n7.2\tYour obligations shall not extend to any claim for violation or infringement resulting solely from your compliance with any specific or direct written instructions from Us if such infringement would have been avoided but for such compliance.
\r\n\r\n8.1\tBoth parties expressly agree and understand that You are an independent contractor and nothing herein nor the services rendered hereunder is meant, or shall be construed in any way or manner, to create a relationship of employer and employee, principal and agent, partners or any other relationship other than that of independent parties contracting with each other solely for the purpose of carrying out the provisions of these Terms. Accordingly, You acknowledge and agree that You shall not be entitled to any benefits provided by Us to our employees. You shall be responsible for any and all out-of-pocket expenses incurred in connection with performing the Services. In addition, You shall have sole and exclusive responsibility for the payment of all federal, state and local income taxes, for all employment and disability insurance and for Social Security and other similar taxes with respect to any compensation provided by Us hereunder. You further agree that if We pay or become liable for such taxes or related civil penalties or interest as a result of your failure to pay taxes or report same, or due to our failure to withhold taxes, You shall indemnify and hold us harmless for any such liability. You shall assume and accept all responsibilities which are imposed on independent contractors by any statute, regulation, rule of law, or otherwise. You are not our agent and are not authorized and shall not have the power or authority to bind Us or incur any liability or obligation, or act on behalf of Us. At no time shall You represent that You are our agent, or that any of the views, advice, statements and/or information that may be provided while performing the Services are ours.
\r\n\r\n8.2\tWe are entitled to provide You with general guidance to assist You in completing the scope of work to our satisfaction, You are ultimately responsible for directing and controlling the performance of the task and the scope of work, in accordance with these Terms. You shall use your best efforts, energy and skill in your own name and in such manner as You see fit.
',agreeabilityType:"Electronically-agreeable",serverInformation:{serverName:"Topcoder API",apiVersion:"0.0.1",requestDuration:52,currentTime:1504892902498},requesterInformation:{id:"d8c441f8332161f71533f368c09aeead856e4366-K1RdFai7LCAgXVu5",remoteIP:"12.34.56.78",receivedParams:{apiVersion:"v2",termsOfUseId:"21193",action:"getTermsOfUse"}}}},function(e){e.exports={termsOfUseId:21193,title:"Standard Terms for Topcoder Competitions v2.1",url:"",agreeabilityType:"Electronically-agreeable",text:'\r\n\r\n\r\n\r\n\r\n\r\nBY E-MAIL: | \r\nGC@appirio.com | \r\n
BY MAIL: | \r\nDan Lascell\r\n\r\nTopcoder, Inc.\r\n\r\n760 Market Street\r\n\r\nSan Francisco, CA 94102 | \r\n
BY PHONE: | \r\n(650) 268-9911 | \r\n
\r\nOnce signed, you will be automatically added to the NDA terms of use and notified by email. \r\n
',agreed:!1,docusignTemplateId:"fake-template-id",serverInformation:{serverName:"TopCoder API",apiVersion:"0.0.1",requestDuration:4,currentTime:1504891122158},requesterInformation:{id:"d9994de712597c11d1caad64996d9fa0d9b4aa2c-w2VCwwGwnN6EeyhK",remoteIP:"12.34.56.789",receivedParams:{apiVersion:"v2",termsOfUseId:"21153",action:"getTermsOfUse"}}}},function(e){e.exports={terms:[{termsOfUseId:21193,title:"Standard Terms for Topcoder Competitions v2.1",url:"",agreeabilityType:"Electronically-agreeable",templateId:null},{termsOfUseId:21153,title:"Appirio NDA v2.0",url:"http://community.topcoder.com/tc?module=Terms&tuid=21153",agreeabilityType:"DocuSignable",templateId:"fake-template-id"}],serverInformation:{serverName:"Topcoder API",apiVersion:"0.0.1",requestDuration:11471,currentTime:1504879510947},requesterInformation:{id:"456f987dee6e9823179c8184fd3509ffdf9c613a-FyefLdEpb8UHgFQF",remoteIP:"12.34.567.890",receivedParams:{role:"Submitter",noauth:"true",apiVersion:"v2",challengeId:"30059255",action:"getChallengeTerms"}}}},function(e){e.exports={terms:[{termsOfUseId:21153,title:"Appirio NDA v2.0",url:"http://community.topcoder.com/tc?module=Terms&tuid=21153",agreeabilityType:"DocuSignable",agreed:!1,templateId:"fake-template-id"},{termsOfUseId:20704,title:"Standard Reviewer Terms v1.0",url:"",agreeabilityType:"Electronically-agreeable",agreed:!1,templateId:null}],serverInformation:{serverName:"Topcoder API",apiVersion:"0.0.1",requestDuration:29,currentTime:1504878884618},requesterInformation:{id:"1b37607c519c318194ce6da08c519c0a3f7c9855-7FSFCyd6oSX2mV6Z",remoteIP:"12.34.567.890",receivedParams:{role:"Submitter",apiVersion:"v2",challengeId:"30059255",action:"getChallengeTerms"}}}},function(e){e.exports={termsOfUseId:20704,title:"Standard Reviewer Terms v1.0",url:"",text:'THESE ARE THE TERMS AND CONDITIONS ("TERMS") UNDER WHICH YOU AGREE TO WORK UNDER AS A TOPCODER REVIEW BOARD MEMBER. THESE TERMS AND CONDITIONS AFFECT YOUR RIGHTS AND YOU SHOULD READ THEM CAREFULLY BEFORE AGREEING TO THEM. IN THESE TERMS AND CONDITIONS, "WE," "US," "ITS" AND "OUR" REFER TO TOPCODER, INC. AND "YOU" AND "YOUR" REFER TO YOU.
\r\n\r\nIt is understood that We need, and You have, expertise in evaluating and critiquing software designs and/or software development solutions. Furthermore, You agree that You are ready, willing, and able to undertake the performance of evaluating and critiquing such software designs and/or software development solutions submitted to Us, and You agree to assign and transfer your rights as a result of performing such services.
\r\n\r\nIn consideration of the premises and the mutual promises and covenants set forth herein, and for other good and valuable consideration, the receipt and sufficiency of which are hereby acknowledged, the parties agree as follows:
\r\n\r\nAs used in these Terms, the following capitalized terms shall have the following meanings unless otherwise indicated:
\r\n\r\n1.1.\t"Development(s)" shall mean any idea, design, concept, development, component, algorithm, process, method, formula, code, software, technique, technology, discovery or improvement, whether or not patentable, made, conceived, created, discovered, invented or reduced to practice by You in connection with the performance of services hereunder.
\r\n\r\n1.2.\t"Intellectual Property Rights" shall mean all intellectual property rights worldwide arising under statutory or common law or by contract and whether or not perfected, now existing or hereafter filed, issued or acquired, including all patent rights; all rights associated with works of authorship including copyrights and moral rights; rights relating to the protection of trade secrets and confidential information; and any right analogous to those set forth herein and any other proprietary rights relating to intangible property, other than Trademarks.
\r\n\r\n1.3.\t"TopCoder Information" shall mean TopCoder\'s and TopCoder Software\'s specifications, descriptions, architecture, plans, interfaces, and code for TopCoder\'s and TopCoder Software\'s hardware, software, and web site; TopCoder\'s competitions and competition operation procedures; TopCoder\'s and TopCoder Software\'s business and operational plans; and derivatives of the foregoing. The TopCoder Information shall be Confidential Information hereunder.
\r\n\r\n1.4.\t"Software Component" shall mean all software and related materials, technology and documentation (including without limitation design documents, source code and object code) to be evaluated and assessed by You for Us hereunder in accordance with our requirements, as set forth herein and in other documents provided by Us. The Software Component shall be Confidential Information hereunder.
\r\n\r\n2.1\tYou hereby agree to provide services relating to the evaluation and assessment of the Software Component. You agree to perform such services according to and in conformity with the following specifications, in addition to any specifications and/or scheduled provided by Us in our sole discretion (the "Services"):
\r\n\r\n2.2\tYou agree to commit sufficient time and resources to perform the Services according to the schedule set forth by Us. You shall promptly notify Us of any circumstances, as such circumstances arise, that may reasonably be anticipated to lead to a material deviation from the schedule.
\r\n\r\n2.3\tYou agree to keep Us updated, promptly upon our request, of any progress, problems, and/or developments of which You are aware regarding the Services. We shall have the right to require such updates in writing from You in a format specified by Us or acceptable to Us in our sole discretion. You shall conduct and conclude the Services in a professional manner.
\r\n\r\n3.1\tFee. In consideration for performance of the Services required by You, We shall pay You the fee set forth on TopCoder\'s website and/or in other correspondence from Us to You (the "Fee"). The Fee shall be in U.S. Dollars and may be paid in installments, as set forth on our website or in other correspondence from Us. The Fee shall be paid upon the conclusion of the review period, and once completed scorecards have been received, provided the completed scorecards are submitted to Us by the deadline as set forth on the website and/or in the correspondence from Us.
\r\n\r\n3.2\tRoyalty Payments.
\r\n \r\n(a)\tDefinitions. As used in this Section 3, the following capitalized terms shall have the following meanings unless otherwise indicated:
\r\n(b)\tIn consideration of Your evaluation of the Software Components and performance of Your obligations hereunder, We may pay to You a royalty (the "Royalty Payment"). The Royalty Payment to be paid shall be a portion of the Royalty Pool. The Royalty Pool shall be distributed as follows:
\r\n\r\n3.3\tTotal Payment. The sum of the Fee and the Royalty Payments shall be the total payment due to You. Any and all out-of-pocket expenses incurred by You in connection with performing the obligations hereunder are your sole responsibility. We will not reimburse You for any expenses incurred.
\r\n\r\n3.4\tYou shall not be entitled to receive any other compensation or any benefits from Us in connection with the Services. Except as otherwise required by law, We shall not withhold any sums or payments made to You for social security or other federal, state or local tax liabilities or contributions, and all withholdings, liabilities, and contributions shall be solely your responsibility. Further, You understand and agree that the Services are not covered under the unemployment compensation laws and are not intended to be covered by workers\' compensation laws.
\r\n\r\n4.1\tYou hereby acknowledge and agree that We own, solely and exclusively, all right, title and interest, including all Intellectual Property Rights, in and to the TopCoder Information. In addition, You hereby irrevocably and unconditionally transfer and assign to Us all right, title and interest You had, have, may have or acquire in or to all Developments and Software Components, and You agree to execute and deliver such documents, certificates, assignments and other writings, and take such other actions as may be necessary or desirable to vest in Us the ownership rights granted to Us hereunder.
\r\n\r\n4.2\tYou further agree that any and all works of authorship created, authored or developed by You hereunder shall be deemed to be "works made for hire" within the meaning of the United States Copyright Law and, as such, all rights therein including copyright shall belong solely and exclusively to Us from the time of their creation. To the extent any such work of authorship may not be deemed to be a work made for hire, You agree to, and do hereby, irrevocably and unconditionally transfer and assign to Us all right, title and interest including copyright in and to such work.
\r\n\r\n4.3\tYou agree that if We are unable, because of your unavailability, or for any other reason, to secure your signature to apply for or to pursue any application for any United States or foreign patents, mask work, copyright or trademark registrations covering the assignments to Us above, then You hereby irrevocably designates and appoints Us and your duly authorized officers and agents as your agent and attorney in fact, to act for and in your behalf and stead to execute and file any such applications and to do all other lawfully permitted acts to further the prosecution and issuance of patents, copyright, mask work and trademark registrations thereon with the same legal force and effect as if executed by your authorized agent.
\r\n\r\n4.4\tAll Intellectual Property Rights owned by a party as of the date You agree to these Terms shall remain the property of such party and no licenses or other rights with respect to such intellectual property are granted to the other party except as expressly set forth herein.
\r\n\r\n4.5\tNothing in these terms shall be construed as granting You any right or license under any of our Intellectual Property Right (including any rights We may have in any patents, copyrights, trademarks, service marks or any trade secrets), by implication, estoppel or otherwise, except as expressly set forth herein.
\r\n\r\n5.1\t"Confidential Information" shall mean any information, in whatever form, provided by Us to You with obligation of confidentiality, or designated by Us in writing as confidential, proprietary or marked with words of like import when provided to You, and information orally conveyed if We state at the time of oral conveyance or promptly thereafter that such information is confidential. Notwithstanding anything to the contrary contained herein, information about or relating to our software, our system interfaces, our hardware and software architecture, our business, operational and marketing plans, our member lists and database, all information and technology provided by Us to You to enable You to perform your obligations hereunder, TopCoder Information, and any and all Developments shall be considered Confidential Information.
\r\n\r\n5.2\tConfidential Information shall not include information which (a) was in your possession without confidentiality restriction prior to disclosure by Us hereunder; (b) at or after the time of disclosure by Us becomes generally available to the public through no act or omission on our part; (c) is developed by You independently of and without reference to any Confidential Information You receive from Us; or (d) has come into your possession without confidentiality restriction from a third party and such third party is under no obligation to Us to maintain the confidentiality of such information.
\r\n\r\n5.3\tYou acknowledge the confidential and proprietary nature of Confidential Information and agree (i) to hold Confidential Information in confidence and to take all reasonable precautions to protect such Confidential Information (including, without limitation, all precautions You employ with respect to your own confidential materials), (ii) not to divulge any such Confidential Information to any third person; and (iii) not to make any use whatsoever of such Confidential Information except as expressly authorized herein.
\r\n\r\n5.4\tIn the event You are ordered to disclose Confidential Information pursuant to a judicial or government request, requirement or order, You shall promptly notify Us and upon our request, You shall, at our expense, take reasonable steps to assist Us in contesting such request, requirement or order or in otherwise protecting our rights prior to disclosure.
\r\n\r\n5.5\tYou agree not to reproduce or copy by any means Confidential Information, except as reasonably required to perform the Services. Upon termination of your performance of the Services as a review board member, your right to use Confidential Information shall immediately terminate. In addition, upon such termination, or upon demand by Us at any time, You shall return promptly to Us or destroy, at our option, all tangible materials and computer data that disclose or embody Confidential Information.
\r\n\r\n5.6\tYou agree that any breach of these terms by You could cause irreparable damage to Us. In view of the difficulties of placing a monetary value on the Confidential Information, We shall have, in addition to any and all remedies of law, the right to an injunction or other equitable relief, and may be entitled to a preliminary and final injunction without the necessity of posting any bond or undertaking in connection therewith to prevent any further breach or further unauthorized use of Confidential Information. This remedy is separate from any other remedy We may have.
\r\n\r\n6.1\tYou represent and warrant that:\r\n
7.1\tYou shall indemnify, hold harmless and defend Us and our customers from and against any and all suits, actions, damages, costs, losses, expenses (including settlement awards and reasonable attorneys\' fees) and other liabilities arising from or in connection with any claim alleging that, to your knowledge, any Development and/or Software Component violates any trade secret right, or infringes any copyright, patent, trademark, or other intellectual property interest, in any country, and shall pay all costs and damages awarded. We shall promptly notify You of any such claim of which We are aware.
\r\n\r\n7.2\tYour obligations shall not extend to any claim for violation or infringement resulting solely from your compliance with any specific or direct written instructions from Us if such infringement would have been avoided but for such compliance.
\r\n\r\n8.1\tBoth parties expressly agree and understand that You are an independent contractor and nothing herein nor the services rendered hereunder is meant, or shall be construed in any way or manner, to create a relationship of employer and employee, principal and agent, partners or any other relationship other than that of independent parties contracting with each other solely for the purpose of carrying out the provisions of these Terms. Accordingly, You acknowledge and agree that You shall not be entitled to any benefits provided by Us to our employees. You shall be responsible for any and all out-of-pocket expenses incurred in connection with performing the Services. In addition, You shall have sole and exclusive responsibility for the payment of all federal, state and local income taxes, for all employment and disability insurance and for Social Security and other similar taxes with respect to any compensation provided by Us hereunder. You further agree that if We pay or become liable for such taxes or related civil penalties or interest as a result of your failure to pay taxes or report same, or due to our failure to withhold taxes, You shall indemnify and hold us harmless for any such liability. You shall assume and accept all responsibilities which are imposed on independent contractors by any statute, regulation, rule of law, or otherwise. You are not our agent and are not authorized and shall not have the power or authority to bind Us or incur any liability or obligation, or act on behalf of Us. At no time shall You represent that You are our agent, or that any of the views, advice, statements and/or information that may be provided while performing the Services are ours.
\r\n\r\n8.2\tWe are entitled to provide You with general guidance to assist You in completing the scope of work to our satisfaction, You are ultimately responsible for directing and controlling the performance of the task and the scope of work, in accordance with these Terms. You shall use your best efforts, energy and skill in your own name and in such manner as You see fit.
',agreeabilityType:"Electronically-agreeable",serverInformation:{serverName:"Topcoder API",apiVersion:"0.0.1",requestDuration:52,currentTime:1504892902498},requesterInformation:{id:"d8c441f8332161f71533f368c09aeead856e4366-K1RdFai7LCAgXVu5",remoteIP:"12.34.56.78",receivedParams:{apiVersion:"v2",termsOfUseId:"21193",action:"getTermsOfUse"}}}},function(e){e.exports={termsOfUseId:21193,title:"Standard Terms for Topcoder Competitions v2.1",url:"",agreeabilityType:"Electronically-agreeable",text:'\r\n\r\n\r\n\r\n\r\n\r\nBY E-MAIL: | \r\nGC@appirio.com | \r\n
BY MAIL: | \r\nDan Lascell\r\n\r\nTopcoder, Inc.\r\n\r\n760 Market Street\r\n\r\nSan Francisco, CA 94102 | \r\n
BY PHONE: | \r\n(650) 268-9911 | \r\n
Action
+ * [.getMoreChallenges(bucket)](#module_actions.challenge-listing.getMoreChallenges) ⇒ Action
+ * [.getAllActiveChallengesInit(uuid)](#module_actions.challenge-listing.getAllActiveChallengesInit) ⇒ Action
+ * [.getAllActiveChallengesDone(uuid, tokenV3)](#module_actions.challenge-listing.getAllActiveChallengesDone) ⇒ Action
+ * [.getActiveChallengesInit(uuid, page, frontFilter, sort, bucket)](#module_actions.challenge-listing.getActiveChallengesInit) ⇒ Action
+ * [.getActiveChallengesDone(
+ uuid, page, backendFilter, tokenV3, frontFilter, sort, bucket,
+)](#module_actions.challenge-listing.getActiveChallengesDone) ⇒ Action
+ * [.getRestActiveChallengesInit(uuid)](#module_actions.challenge-listing.getRestActiveChallengesInit) ⇒ Action
+ * [.getRestActiveChallengesDone(
+ uuid, tokenV3, backendFilter, frontFilter, sort, bucket,
+)](#module_actions.challenge-listing.getRestActiveChallengesDone) ⇒ Action
+ * [.getChallengeSubtracksInit()](#module_actions.challenge-listing.getChallengeSubtrackInit) ⇒ Action
+ * [.getChallengeSubtracksDone()](#module_actions.challenge-listing.getChallengeSubtracksDone) ⇒ Action
+ * [.getChallengeTagsInit()](#module_actions.challenge-listing.getChallengeTagsInit) ⇒ Action
+ * [.getChallengeTagsDone()](#module_actions.challenge-listing.getChallengeTagsDone) ⇒ Action
+ * [.getPastChallengesInit(uuid, page, frontFilter, sort)](#module_actions.challenge-listing.getPastChallengesInit) ⇒ Action
+ * [.getPastChallengesDone(uuid, page, filter, tokenV3, frontFilter, sort)](#module_actions.challenge-listing.getPastChallengesDone) ⇒ Action
+ * [.getReviewOpportunitiesInit(uuid, page, sort)](#module_actions.challenge-listing.getReviewOpportunitiesInit) ⇒ Action
+ * [.getReviewOpportunitiesDone(uuid, page, tokenV3, sort, frontFilter)](#module_actions.challenge-listing.getReviewOpportunitiesDone) ⇒ Action
+ * [.getSrmsInit(uuid)](#module_actions.challenge-listing.getSrmsInit) ⇒ Action
+ * [.getSrmsDone(uuid, handle, params, tokenV3)](#module_actions.challenge-listing.getSrmsDone) ⇒ Action
+ * [.expandTag(id)](#module_actions.challenge-listing.expandTag) ⇒ Action
+ * [.selectCommunity()](#module_actions.challenge-listing.selectCommunity) ⇒ Action
+ * [.setFilter()](#module_actions.challenge-listing.setFilter) ⇒ Action
+ * [.setDatepickerStatus(status)](#module_actions.challenge-listing.setDatepickerStatus) ⇒ Action
+ * [.setSort(bucket, sort)](#module_actions.challenge-listing.setSort) ⇒ Action
+
+
+
+### actions.challenge-listing.dropChallenges(bucket) ⇒ Action
+Creates an action that drops from Redux store all challenges-list related loaded.
+**Kind**: static method of [actions.challenge-listing
](#module_actions.challenge-listing)
+
+| Param | Type | Description |
+| --- | --- | --- |
+| bucket | String
| Bucket name |
+
+
+
+### actions.challenge-listing.getMoreChallenges(bucket) ⇒ Action
+Creates an action that get more challenges of bucket.
+**Kind**: static method of [actions.challenge-listing
](#module_actions.challenge-listing)
+
+| Param | Type | Description |
+| --- | --- | --- |
+| bucket | String
| Bucket name |
+
+
+
+### actions.challenge-listing.getAllActiveChallengesInit(uuid) ⇒ Action
+Creates an action that signals beginning of all active challenges loading.
+**Kind**: static method of [actions.challenge-listing
](#module_actions.challenge-listing)
+
+| Param | Type | Description |
+| --- | --- | --- |
+| uuid | String
| UUID of the operation (the same should be passed into the corresponding |
+
+
+
+### actions.challenge-listing.getAllActiveChallengesInit(uuid, tokenV3) ⇒ Action
+Creates an action that loads all active challenges.
+**Kind**: static method of [actions.challenge-listing
](#module_actions.challenge-listing)
+
+| Param | Type | Description |
+| --- | --- | --- |
+| uuid | String
| UUID of the operation (the same should be passed into the corresponding |
+| tokenV3 | String
| Topcoder v3 auth token. |
+
+
+### actions.challenge-listing.getActiveChallengesInit(uuid, page, frontFilter, sort, bucket) ⇒ Action
+Creates an action that signals beginning of active challenges of bucket loading.
+**Kind**: static method of [actions.challenge-listing
](#module_actions.challenge-listing)
+
+| Param | Type | Description |
+| --- | --- | --- |
+| uuid | String
| UUID of the operation (the same should be passed into the corresponding |
+| page | Number
| Page number of fetch data |
+| frontFilter | Object
| Filter Object from Client |
+| sort | String
| Sort name |
+| bucket | String
| Bucket name |
+
+
+
+### actions.challenge-listing.getActiveChallengesDone(
+ uuid, page, backendFilter, tokenV3, frontFilter, sort, bucket,
+) ⇒ Action
+Creates an action that loads active challenges of bucket.
+**Kind**: static method of [actions.challenge-listing
](#module_actions.challenge-listing)
+
+| Param | Type | Description |
+| --- | --- | --- |
+| uuid | String
| UUID of the operation (the same should be passed into the corresponding |
+| page | Number
| Page number of fetch data |
+| backendFilter | Object
| Filter Object from Backend |
+| tokenV3 | String
| Topcoder v3 auth token |
+| frontFilter | Object
| Filter Object from Client |
+| sort | String
| Sort name |
+| bucket | String
| Bucket name |
+
+
+
+### actions.challenge-listing.getRestActiveChallengesInit(uuid) ⇒ Action
+Creates an action that signals beginning of rest active challenges of bucket loading.
+**Kind**: static method of [actions.challenge-listing
](#module_actions.challenge-listing)
+
+| Param | Type | Description |
+| --- | --- | --- |
+| uuid | String
| UUID of the operation (the same should be passed into the corresponding |
+
+
+
+### actions.challenge-listing.getRestActiveChallengesDone(
+ uuid, tokenV3, backendFilter, frontFilter, sort, bucket,
+) ⇒ Action
+Creates an action that loads rest active challenges of bucket.
+**Kind**: static method of [actions.challenge-listing
](#module_actions.challenge-listing)
+
+| Param | Type | Description |
+| --- | --- | --- |
+| uuid | String
| UUID of the operation (the same should be passed into the corresponding |
+| tokenV3 | String
| Topcoder v3 auth token |
+| backendFilter | Object
| Filter Object from Backend |
+| frontFilter | Object
| Filter Object from Client |
+| sort | String
| Sort name |
+| bucket | String
| Bucket name |
+
+
+
+### actions.challenge-listing.getChallengeSubtracksInit() ⇒ Action
+Creates an action that signals beginning of challenge substrcks loading.
+**Kind**: static method of [actions.challenge-listing
](#module_actions.challenge-listing)
+
+
+### actions.challenge-listing.getChallengeSubtracksDone()⇒ Action
+Creates an action that loads challenge substrcks.
+**Kind**: static method of [actions.challenge-listing
](#module_actions.challenge-listing)
+
+
+### actions.challenge-listing.getChallengeTagsInit() ⇒ Action
+Creates an action that signals beginning of challenge tags loading.
+**Kind**: static method of [actions.challenge-listing
](#module_actions.challenge-listing)
+
+
+### actions.challenge-listing.getChallengeTagsDone()⇒ Action
+Creates an action that loads challenge tags.
+**Kind**: static method of [actions.challenge-listing
](#module_actions.challenge-listing)
+
+
+### actions.challenge-listing.getPastChallengesInit(uuid, page, frontFilter, sort) ⇒ Action
+Creates an action that signals beginning of past challenges loading.
+**Kind**: static method of [actions.challenge-listing
](#module_actions.challenge-listing)
+
+| Param | Type | Description |
+| --- | --- | --- |
+| uuid | String
| UUID of the operation (the same should be passed into the corresponding |
+| page | Number
| Page number of fetch data |
+| frontFilter | Object
| Filter Object from Client |
+| sort | String
| Sort name |
+
+
+
+### actions.challenge-listing.getPastChallengesDone(uuid, page, filter, tokenV3, frontFilter, sort) ⇒ Action
+Creates an action that loads past challenges.
+**Kind**: static method of [actions.challenge-listing
](#module_actions.challenge-listing)
+
+| Param | Type | Description |
+| --- | --- | --- |
+| uuid | String
| UUID of the operation (the same should be passed into the corresponding |
+| page | Number
| Page number of fetch data |
+| filter | Object
| Filter Object from Backend |
+| tokenV3 | String
| Topcoder v3 auth token |
+| frontFilter | Object
| Filter Object from Client |
+| sort | String
| Sort name |
+
+
+
+### actions.challenge-listing.getReviewOpportunitiesInit(uuid, page, sort) ⇒ Action
+Creates an action that signals beginning of review opportunities loading.
+**Kind**: static method of [actions.challenge-listing
](#module_actions.challenge-listing)
+
+| Param | Type | Description |
+| --- | --- | --- |
+| uuid | String
| UUID of the operation (the same should be passed into the corresponding |
+| page | Number
| Page number of fetch data |
+| sort | String
| Sort name |
+
+
+
+### actions.challenge-listing.getReviewOpportunitiesDone(uuid, page, tokenV3, sort, frontFilter) ⇒ Action
+Creates an action that loads review oportunites.
+**Kind**: static method of [actions.challenge-listing
](#module_actions.challenge-listing)
+
+| Param | Type | Description |
+| --- | --- | --- |
+| uuid | String
| UUID of the operation (the same should be passed into the corresponding |
+| page | Number
| Page number of fetch data |
+| tokenV3 | String
| Topcoder v3 auth token |
+| sort | String
| Sort name |
+| frontFilter | Object
| Filter Object from Client |
+
+
+
+
+### actions.challenge-listing.getSrmsInit(uuid) ⇒ Action
+Creates an action that signals beginning of SRMs loading.
+**Kind**: static method of [actions.challenge-listing
](#module_actions.challenge-listing)
+
+| Param | Type | Description |
+| --- | --- | --- |
+| uuid | String
| UUID of the operation (the same should be passed into the corresponding |
+
+
+### actions.challenge-listing.getSrmsDone(uuid, handle, params, tokenV3) ⇒ Action
+Creates an action that SRMs.
+**Kind**: static method of [actions.challenge-listing
](#module_actions.challenge-listing)
+
+| Param | Type | Description |
+| --- | --- | --- |
+| uuid | String
| UUID of the operation (the same should be passed into the corresponding |
+| handle | String
| Topcoder member handle |
+| params | Object
| params of fetch data |
+| tokenV3 | String
| Topcoder v3 auth token |
+
+
+
+### actions.challenge-listing.expandTag(id) ⇒ Action
+Creates an action that set tag id
+**Kind**: static method of [actions.challenge-listing
](#module_actions.challenge-listing)
+
+| Param | Type | Description |
+| --- | --- | --- |
+| id | String
| Id of tag |
+
+
+
+### actions.challenge-listing.selectCommunity() ⇒ Action
+Creates an action that pass community id
+**Kind**: static method of [actions.challenge-listing
](#module_actions.challenge-listing)
+
+
+### actions.challenge-listing.setFilter() ⇒ Action
+Creates an action that pass filter value
+**Kind**: static method of [actions.challenge-listing
](#module_actions.challenge-listing)
+
+
+### actions.challenge-listing.setDatepickerStatus(status) ⇒ Action
+Creates an action that set Datepicker status
+**Kind**: static method of [actions.challenge-listing
](#module_actions.challenge-listing)
+
+| Param | Type | Description |
+| --- | --- | --- |
+| status | Boolean
| Status datapicker |
+
+
+
+### actions.challenge-listing.setSort(bucket, sort) ⇒ Action
+Creates an action that set sort of bucket
+**Kind**: static method of [actions.challenge-listing
](#module_actions.challenge-listing)
+
+| Param | Type | Description |
+| --- | --- | --- |
+| bucket | String
| Bucket name |
+| sort | String
| Sort name |
diff --git a/docs/buckets.md b/docs/buckets.md
new file mode 100644
index 00000000..80072bd3
--- /dev/null
+++ b/docs/buckets.md
@@ -0,0 +1,50 @@
+
+
+## buckets
+Collection of buckets of challenge
+
+* [challenge_buckets](#module_challenge_buckets)
+ * [.BUCKETS](#module_challenge_buckets.BUCKETS)
+ * [.BUCKET_DATA](#module_challenge_buckets.BUCKET_DATA)
+ * [.getBuckets(res)](#module_challenge_buckets.getBuckets) ⇒ Promise
+ * [.isReviewOpportunitiesBucket(res)](#module_challenge_buckets.isReviewOpportunitiesBucket) ⇒ Promise
+ * [.registerBucket](#module_challenge_buckets.registerBucket)
+
+
+### challenge_buckets.BUCKETS
+Bucket types
+**Kind**: static constant of [challenge_buckets
](#module_challenge_buckets)
+
+
+
+### challenge_buckets.BUCKET_DATA
+The data of bucket
+**Kind**: static constant of [challenge_buckets
](#module_challenge_buckets)
+
+
+
+### challenge_buckets.getBuckets(userHandle) ⇒ Promise
+Returns configuration of all possible challenge buckets.
+**Kind**: static method of [challenge_buckets
](#module_challenge_buckets)
+**Returns**: Promise
- Resolves to the payload.
+
+| Param | Type |
+| --- | --- |
+| res | Object
|
+
+
+
+### challenge_buckets.isReviewOpportunitiesBucket(bucket) ⇒ Promise
+Tests if a given bucket is of any of the Review Opportunities types
+**Kind**: static method of [challenge_buckets
](#module_challenge_buckets)
+**Returns**: Promise
- Resolves to the payload.
+
+| Param | Type |
+| --- | --- |
+| res | Boolean
|
+
+
+### challenge_buckets.registerBucket(id, bucket) ⇒ Promise
+Registers a new bucket.
+**Kind**: static method of [challenge_buckets
](#module_challenge_buckets)
+
diff --git a/docs/index.md b/docs/index.md
index ec065107..185c46d5 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -9,6 +9,11 @@
actions.challenge
Actions related to Topcoder challenges APIs.
Actions related to Topcoder challenge-listing APIs.
+Actions related to Direct API: access to projects, billing accounts, @@ -71,6 +76,11 @@ actions and reducer; thus, this module.
Reducer for actions.challenge actions.
State segment managed by this reducer has the following strcuture:
Reducer for actions.challenge-listing actions.
+Reducer for handling the results of Direct-related actions.
@@ -275,4 +285,19 @@ the proxy will forward them to the service only if LOG_ENTRIES_TOKEN is set).Utility functions for time/date related stuff
Collection of challenge sort.
+Collection of challenge buckets.
+Collection of url function.
+Promise
+ * _inner_
+ * [~dropChallenges(state, action)](#module_reducers.challenge-listing..dropChallenges) ⇒ Object
+ * [~getMoreChallenges(state, action)](#module_reducers.challenge-listing..getMoreChallenges) ⇒ Object
+ * [~expandTag(state, action)](#module_reducers.challenge-listing..expandTag) ⇒ Object
+ * [~getAllActiveChallengesInit(state, action)](#module_reducers.challenge-listing..onGetAllActiveChallengesInit) ⇒ Object
+ * [~getAllActiveChallengesDone(state, action)](#module_reducers.challenge-listing..onGetAllActiveChallengesDone) ⇒ Object
+ * [~getActiveChallengesInit(state, action)](#module_reducers.challenge-listing..getActiveChallengesInit) ⇒ Object
+ * [~getActiveChallengesDone(state, action)](#module_reducers.challenge-listing..getActiveChallengesDone) ⇒ Object
+ * [~getRestActiveChallengesInit(state, action)](#module_reducers.challenge-listing..getRestActiveChallengesInit) ⇒ Object
+ * [~getRestActiveChallengesDone(state, action)](#module_reducers.challenge-listing..getRestActiveChallengesDone) ⇒ Object
+ * [~getChallengeSubtracksInit()](#module_reducers.challenge-listing..getChallengeSubtracksInit) ⇒ Object
+ * [~getChallengeSubtracksDone(state, action)](#module_reducers.challenge-listing..getChallengeSubtracksDone) ⇒ Object
+ * [~getChallengeTagsInit()](#module_reducers.challenge-listing..getChallengeTagsInit) ⇒ Object
+ * [~getChallengeTagsDone(state, action)](#module_reducers.challenge-listing..getChallengeTagsDone) ⇒ Object
+ * [~getPastChallengesInit(state, action)](#module_reducers.challenge-listing..getPastChallengesInit) ⇒ Object
+ * [~getReviewOpportunitiesInit(state, action)](#module_reducers.challenge-listing..getReviewOpportunitiesInit) ⇒ Object
+ * [~getReviewOpportunitiesDone(state, action)](#module_reducers.challenge-listing..getReviewOpportunitiesDone) ⇒ Object
+ * [~getSrmsInit(state, action)](#module_reducers.challenge-listing..getSrmsInit) ⇒ Object
+ * [~getSrmsDone(state, action)](#module_reducers.challenge-listing..getSrmsDone) ⇒ Object
+ * [~selectCommunity(state, action)](#module_reducers.challenge-listing..selectCommunity) ⇒ Object
+ * [~setFilter(state, action)](#module_reducers.challenge-listing..setFilter) ⇒ Object
+ * [~setSort(state, action)](#module_reducers.challenge-listing..setSort) ⇒ Object
+ * [~setDatePickerStatus(state, action)](#module_reducers.challenge-listing..setDatePickerStatus) ⇒ Object
+ * [~create(initialState)](#module_reducers.challenge..create) ⇒ function
+
+
+### reducers.challenge-listing.default
+Reducer with default intial state.
+**Kind**: static property of [reducers.challenge-listing
](#module_reducers.challenge-listing)
+
+
+### reducers.challenge-listing.factory() ⇒ Promise
+Factory which creates a new reducer with its initial state tailored to the
+given options object, if specified (for server-side rendering). If options
+object is not specified, it creates just the default reducer. Accepted options are:
+
+**Kind**: static method of [reducers.challenge-listing
](#module_reducers.challenge-listing)
+**Resolves**: Function(state, action): state
New reducer.
+
+
+### reducers.challenge-listing~dropChallenges(state, action) ⇒ Object
+Handles CHALLENGE_LISTING/DROP_CHALLENGES action.
+**Kind**: inner method of [reducers.challenge-listing
](#module_reducers.challenge-listing)
+**Returns**: Object
- New state
+
+| Param | Type |
+| --- | --- |
+| state | Object
|
+| action | Object
|
+
+
+### reducers.challenge-listing~getMoreChallenges(state, action) ⇒ Object
+Handles CHALLENGE_LISTING/GET_MORE_CHALLENGES action.
+**Kind**: inner method of [reducers.challenge-listing
](#module_reducers.challenge-listing)
+**Returns**: Object
- New state
+
+| Param | Type |
+| --- | --- |
+| state | Object
|
+| action | Object
|
+
+
+### reducers.challenge-listing~expandTag(state, action) ⇒ Object
+Handles CHALLENGE_LISTING/EXPAND_TAG action.
+**Kind**: inner method of [reducers.challenge-listing
](#module_reducers.challenge-listing)
+**Returns**: Object
- New state
+
+| Param | Type |
+| --- | --- |
+| state | Object
|
+| action | Object
|
+
+
+### reducers.challenge-listing~getAllActiveChallengesInit(state, action) ⇒ Object
+Handles CHALLENGE_LISTING/GET_ALL_ACTIVE_CHALLENGES_INIT action.
+**Kind**: inner method of [reducers.challenge-listing
](#module_reducers.challenge-listing)
+**Returns**: Object
- New state
+
+| Param | Type |
+| --- | --- |
+| state | Object
|
+| action | Object
|
+
+
+### reducers.challenge-listing~getAllActiveChallengesDone(state, action) ⇒ Object
+Handles CHALLENGE_LISTING/GET_ALL_ACTIVE_CHALLENGES_DONE action.
+**Kind**: inner method of [reducers.challenge-listing
](#module_reducers.challenge-listing)
+**Returns**: Object
- New state
+
+| Param | Type |
+| --- | --- |
+| state | Object
|
+| action | Object
|
+
+
+### reducers.challenge-listing~getActiveChallengesInit(state, action) ⇒ Object
+Handles CHALLENGE_LISTING/GET_ACTIVE_CHALLENGES_INIT action.
+**Kind**: inner method of [reducers.challenge-listing
](#module_reducers.challenge-listing)
+**Returns**: Object
- New state
+
+| Param | Type |
+| --- | --- |
+| state | Object
|
+| action | Object
|
+
+
+### reducers.challenge-listing~getActiveChallengesDone(state, action) ⇒ Object
+Handles CHALLENGE_LISTING/GET_ACTIVE_CHALLENGES_DONE action.
+**Kind**: inner method of [reducers.challenge-listing
](#module_reducers.challenge-listing)
+**Returns**: Object
- New state
+
+| Param | Type |
+| --- | --- |
+| state | Object
|
+| action | Object
|
+
+
+### reducers.challenge-listing~getRestActiveChallengesInit(state, action) ⇒ Object
+Handles CHALLENGE_LISTING/GET_REST_ACTIVE_CHALLENGES_INIT action.
+**Kind**: inner method of [reducers.challenge-listing
](#module_reducers.challenge-listing)
+**Returns**: Object
- New state
+
+| Param | Type |
+| --- | --- |
+| state | Object
|
+| action | Object
|
+
+
+### reducers.challenge-listing~getRestActiveChallengesDone(state, action) ⇒ Object
+Handles CHALLENGE_LISTING/GET_REST_ACTIVE_CHALLENGES_DONE action.
+**Kind**: inner method of [reducers.challenge-listing
](#module_reducers.challenge-listing)
+**Returns**: Object
- New state
+
+| Param | Type |
+| --- | --- |
+| state | Object
|
+| action | Object
|
+
+
+### reducers.challenge-listing~getChallengeSubtracksInit() ⇒ Object
+Handles CHALLENGE_LISTING/GET_CHALLENGE_SUBTRACKS_INIT action.
+**Kind**: inner method of [reducers.challenge-listing
](#module_reducers.challenge-listing)
+
+
+### reducers.challenge-listing~getChallengeSubtracksDone(state, action) ⇒ Object
+Handles CHALLENGE_LISTING/GET_CHALLENGE_SUBTRACKS_DONE action.
+**Kind**: inner method of [reducers.challenge-listing
](#module_reducers.challenge-listing)
+
+**Returns**: Object
- New state
+
+| Param | Type |
+| --- | --- |
+| state | Object
|
+| action | Object
|
+
+
+### reducers.challenge-listing~getChallengeTagsInit() ⇒ Object
+Handles CHALLENGE_LISTING/GET_CHALLENGE_TAGS_INIT action.
+**Kind**: inner method of [reducers.challenge-listing
](#module_reducers.challenge-listing)
+
+
+### reducers.challenge-listing~getChallengeTagsDone(state, action) ⇒ Object
+Handles CHALLENGE_LISTING/GET_CHALLENGE_TAGS_DONE action.
+**Kind**: inner method of [reducers.challenge-listing
](#module_reducers.challenge-listing)
+
+**Returns**: Object
- New state
+
+| Param | Type |
+| --- | --- |
+| state | Object
|
+| action | Object
|
+
+
+### reducers.challenge-listing~getPastChallengesInit(state, action) ⇒ Object
+Handles CHALLENGE_LISTING/GET_PAST_CHALLENGES_INIT action.
+**Kind**: inner method of [reducers.challenge-listing
](#module_reducers.challenge-listing)
+
+**Returns**: Object
- New state
+
+| Param | Type |
+| --- | --- |
+| state | Object
|
+| action | Object
|
+
+
+### reducers.challenge-listing~getPastChallengesDone(state, action) ⇒ Object
+Handles CHALLENGE_LISTING/GET_PAST_CHALLENGES_DONE action.
+**Kind**: inner method of [reducers.challenge-listing
](#module_reducers.challenge-listing)
+
+**Returns**: Object
- New state
+
+| Param | Type |
+| --- | --- |
+| state | Object
|
+| action | Object
|
+
+
+### reducers.challenge-listing~getReviewOpportunitiesInit(state, action) ⇒ Object
+Handles CHALLENGE_LISTING/GET_REVIEW_OPPORTUNITIES_INIT action.
+**Kind**: inner method of [reducers.challenge-listing
](#module_reducers.challenge-listing)
+
+**Returns**: Object
- New state
+
+| Param | Type |
+| --- | --- |
+| uuid | Object
|
+| action | Object
|
+
+
+### reducers.challenge-listing~getReviewOpportunitiesDone(state, action) ⇒ Object
+Handles CHALLENGE_LISTING/GET_REVIEW_OPPORTUNITIES_DONE action.
+**Kind**: inner method of [reducers.challenge-listing
](#module_reducers.challenge-listing)
+
+**Returns**: Object
- New state
+
+| Param | Type |
+| --- | --- |
+| uuid | Object
|
+| action | Object
|
+
+
+### reducers.challenge-listing~getSrmsInit(state, action) ⇒ Object
+Handles CHALLENGE_LISTING/GET_SRMS_INIT action.
+**Kind**: inner method of [reducers.challenge-listing
](#module_reducers.challenge-listing)
+
+**Returns**: Object
- New state
+
+| Param | Type |
+| --- | --- |
+| uuid | Object
|
+| action | Object
|
+
+
+### reducers.challenge-listing~getSrmsDone(state, action) ⇒ Object
+Handles CHALLENGE_LISTING/GET_SRMS_DONE action.
+**Kind**: inner method of [reducers.challenge-listing
](#module_reducers.challenge-listing)
+
+**Returns**: Object
- New state
+
+| Param | Type |
+| --- | --- |
+| uuid | Object
|
+| action | Object
|
+
+
+
+### reducers.challenge-listing~selectCommunity(state, action) ⇒ Object
+Handles CHALLENGE_LISTING/SELECT_COMMUNITY action.
+**Kind**: inner method of [reducers.challenge-listing
](#module_reducers.challenge-listing)
+
+**Returns**: Object
- New state
+
+| Param | Type |
+| --- | --- |
+| uuid | Object
|
+| action | Object
|
+
+
+### reducers.challenge-listing~setFilter(state, action) ⇒ Object
+Handles CHALLENGE_LISTING/SET_FILTER action.
+**Kind**: inner method of [reducers.challenge-listing
](#module_reducers.challenge-listing)
+
+**Returns**: Object
- New state
+
+| Param | Type |
+| --- | --- |
+| uuid | Object
|
+| action | Object
|
+
+
+### reducers.challenge-listing~setDatePickerStatus(state, action) ⇒ Object
+Handles CHALLENGE_LISTING/SET_DATEPICKER_STATUS action.
+**Kind**: inner method of [reducers.challenge-listing
](#module_reducers.challenge-listing)
+
+**Returns**: Object
- New state
+
+| Param | Type |
+| --- | --- |
+| uuid | Object
|
+| action | Object
|
+
+
+
+
+### reducers.challenge-listing~create(initialState) ⇒ function
+Creates a new Challenge-listing reducer with the specified initial state.
+
+**Kind**: inner method of [reducers.challenge-listing
](#module_reducers.challenge-listing)
+**Returns**: function
- Challenge-listing reducer.
+
+| Param | Type | Description |
+| --- | --- | --- |
+| initialState | Object
| Optional. Initial state. |
+
diff --git a/docs/sort.md b/docs/sort.md
new file mode 100644
index 00000000..a7f21d61
--- /dev/null
+++ b/docs/sort.md
@@ -0,0 +1,20 @@
+
+
+## sort
+Collection of challenge list sort
+
+* [challenge_sort](#module_challenge_sort)
+ * [.SORTS](#module_challenge_sort.BSORTS)
+ * [.SORTS_DATA](#module_challenge_sort.SORTS_DATA)
+
+
+
+### challenge_sort.SORTS
+Sort types
+**Kind**: static constant of [challenge_sort
](#module_challenge_sort)
+
+
+
+### challenge_sort.SORTS_DATA
+The data of sort
+**Kind**: static constant of [challenge_sort
](#module_challenge_sort)
diff --git a/docs/tc.md b/docs/tc.md
index 8e060798..1345ed26 100644
--- a/docs/tc.md
+++ b/docs/tc.md
@@ -11,23 +11,34 @@ Collection of small Topcoder-related functions.
* [tc](#module_tc)
* [.REVIEW_OPPORTUNITY_TYPES](#module_tc.REVIEW_OPPORTUNITY_TYPES)
* [.getApiResponsePayload(res)](#module_tc.getApiResponsePayload) ⇒ Promise
+ * [.processSRM(res)](#module_tc.processSRM) ⇒ Promise
### tc.REVIEW_OPPORTUNITY_TYPES
Review Opportunity types
-**Kind**: static constant of [tc
](#module_tc)
+**Kind**: static constant of [tc
](#module_tc)
### tc.getApiResponsePayload(res) ⇒ Promise
-Gets payload from a standard success response from TC v2 API; or throws
+Gets payload from a standard success response from TC API; or throws
an error in case of a failure response.
-**Kind**: static method of [tc
](#module_tc)
+**Kind**: static method of [tc
](#module_tc)
**Returns**: Promise
- Resolves to the payload.
| Param | Type |
| --- | --- |
| res | Object
|
+
+### tc.processSRM(res) ⇒ Promise
+process srm to populate additional infomation
+
+**Kind**: static method of [tc
](#module_tc)
+**Returns**: Promise
- Resolves to the payload.
+
+| Param | Type |
+| --- | --- |
+| res | Object
|
diff --git a/docs/url.md b/docs/url.md
new file mode 100644
index 00000000..acdfb108
--- /dev/null
+++ b/docs/url.md
@@ -0,0 +1,27 @@
+
+
+## url
+Collection of url functions.
+
+* [url](#module_url)
+ * [.updateQuery](#module_url.updateQuery)
+ * [.removeTrailingSlash(res)](#module_url.removeTrailingSlash) ⇒ Promise
+
+
+### url.updateQuery
+If executed client-side (determined in this case by the presence of global
+ * window object), this function updates query section of URL; otherwise does
+ * nothing.
+**Kind**: static method of [tc
](#module_url)
+
+
+
+### url.removeTrailingSlash(res) ⇒ Promise
+Cleans/removes trailing slash from url
+**Kind**: static method of [url
](#module_url)
+**Returns**: Promise
- Resolves to the payload.
+
+| Param | Type |
+| --- | --- |
+| res | String
|
+
diff --git a/src/actions/challenge-listing.js b/src/actions/challenge-listing.js
new file mode 100644
index 00000000..d8acf22a
--- /dev/null
+++ b/src/actions/challenge-listing.js
@@ -0,0 +1,450 @@
+/**
+ * Challenge listing actions.
+ */
+
+import _ from 'lodash';
+import { createActions } from 'redux-actions';
+import { decodeToken } from 'tc-accounts';
+import 'isomorphic-fetch';
+import { processSRM, COMPETITION_TRACKS } from '../utils/tc';
+import { services } from '../services';
+import { errors } from '../utils';
+import * as filterUtil from '../utils/challenge/filter';
+import * as config from '../config';
+
+const { fireErrorMessage } = errors;
+const { getService } = services.challenge;
+const { getReviewOpportunitiesService } = services.reviewOpportunities;
+const { PAGE_SIZE, REVIEW_OPPORTUNITY_PAGE_SIZE } = config;
+
+/**
+ * Process filter
+ * Development challenges having Data Science tech tag, still should be
+ * included into data science track.
+ * @param filter
+ * @returns {string}
+ */
+function processFilter(filter) {
+ const newFilter = _.clone(filter);
+ if (_.has(filter, 'track')
+ && filter.track.includes(COMPETITION_TRACKS.DATA_SCIENCE.toUpperCase())
+ && !filter.track.includes(COMPETITION_TRACKS.DEVELOP.toUpperCase())
+ ) {
+ newFilter.track = `${newFilter.track},${COMPETITION_TRACKS.DEVELOP.toUpperCase()}`;
+ }
+ return newFilter;
+}
+
+/**
+ * Private. Loads from the backend all challenges matching some conditions.
+ * @param {Function} getter Given params object of shape { limit, offset }
+ * loads from the backend at most "limit" challenges, skipping the first
+ * "offset" ones. Returns loaded challenges as an array.
+ * @param {Number} page Optional. Next page of challenges to load.
+ * @param {Array} prev Optional. Challenges loaded so far.
+ */
+function getAll(getter, page = 0, prev) {
+ /* Amount of challenges to fetch in one API call. 50 is the current maximum
+ * amount of challenges the backend returns, event when the larger limit is
+ * explicitely required. */
+ return getter({
+ limit: PAGE_SIZE,
+ offset: page * PAGE_SIZE,
+ }).then((res) => {
+ if (res.challenges.length === 0) {
+ return prev || res;
+ }
+ // parse challenges and meta
+ let current = {};
+ if (prev) {
+ current.challenges = prev.challenges.concat(res.challenges);
+ current.meta = res.meta;
+ } else {
+ current = res;
+ }
+ return getAll(getter, 1 + page, current);
+ });
+}
+
+/**
+ * Gets possible challenge subtracks.
+ * @return {Promise}
+ */
+function getChallengeSubtracksDone() {
+ return getService()
+ .getChallengeSubtracks()
+ .then(res => res.sort((a, b) => a.name.localeCompare(b.name)));
+}
+
+/**
+ * Gets possible challenge tags (technologies).
+ * @return {Promise}
+ */
+function getChallengeTagsDone() {
+ return getService()
+ .getChallengeTags()
+ .then(res => res.map(item => item.name)
+ .sort((a, b) => a.localeCompare(b)));
+}
+
+/**
+ * Notifies about reloading of all active challenges. The UUID is stored in the
+ * state, and only challenges fetched by getAllActiveChallengesDone action with
+ * the same UUID will be accepted into the state.
+ * @param {String} uuid
+ * @param {String} page
+ * @param {Object} frontFilter
+ * @param {String} sort
+ * @param {String} bucket
+ * @return {String}
+ */
+function getActiveChallengesInit(uuid, page, frontFilter, sort, bucket) {
+ return {
+ uuid, page, frontFilter, sort, bucket,
+ };
+}
+
+/** TODO: Inspect if the 2 actions bellow can be removed?
+ * They do duplicate what is done in `getActiveChallengesDone` but fetch all challenges
+ * which was refactored in listing-improve
+ */
+function getAllActiveChallengesInit(uuid) {
+ return uuid;
+}
+function getAllActiveChallengesDone(uuid, tokenV3) {
+ const filter = { status: 'ACTIVE' };
+ const service = getService(tokenV3);
+ const calls = [
+ getAll(params => service.getChallenges(filter, params)),
+ ];
+ let user;
+ if (tokenV3) {
+ user = decodeToken(tokenV3).handle;
+ // Handle any errors on this endpoint so that the non-user specific challenges
+ // will still be loaded.
+ calls.push(getAll(params => service.getUserChallenges(user, filter, params)
+ .catch(() => ({ challenges: [] }))));
+ }
+ return Promise.all(calls).then(([ch, uch]) => {
+ /* uch array contains challenges where the user is participating in
+@@ -111,8 +124,8 @@ function getAllActiveChallengesDone(uuid, tokenV3) {
+ * challenges in an efficient way. */
+ if (uch) {
+ const map = {};
+ uch.challenges.forEach((item) => { map[item.id] = item; });
+ ch.challenges.forEach((item) => {
+ if (map[item.id]) {
+ /* It is fine to reassing, as the array we modifying is created just
+ * above within the same function. */
+ /* eslint-disable no-param-reassign */
+ item.users[user] = true;
+ item.userDetails = map[item.id].userDetails;
+ /* eslint-enable no-param-reassign */
+ }
+ });
+ }
+
+ return { uuid, challenges: ch.challenges };
+ });
+}
+
+/**
+ * Gets 1 page of active challenges (including marathon matches) from the backend.
+ * Once this action is completed any active challenges saved to the state before
+ * will be dropped, and the newly fetched ones will be stored there.
+ * Loading of all challenges wil start in background.
+ * @param {String} uuid
+ * @param {Number} page
+ * @param {Object} backendFilter Backend filter to use.
+ * @param {String} tokenV3 Optional. Topcoder auth token v3. Without token only
+ * public challenges will be fetched. With the token provided, the action will
+ * also fetch private challenges related to this user.
+ * @param {Object} frontFilter
+ * @param {String} sort
+ * @param {String} bucket
+
+ * @return {Promise}
+ */
+function getActiveChallengesDone(
+ uuid, page, backendFilter, tokenV3, frontFilter = {}, sort, bucket,
+) {
+ const filter = processFilter({
+ ...backendFilter,
+ status: 'ACTIVE',
+ });
+
+ const service = getService(tokenV3);
+ const calls = [
+ service.getChallenges(filter, {
+ limit: PAGE_SIZE,
+ offset: page * PAGE_SIZE,
+ }),
+ ];
+ let user;
+ if (tokenV3) {
+ user = decodeToken(tokenV3).handle;
+ // Handle any errors on this endpoint so that the non-user specific challenges
+ // will still be loaded.
+ calls.push(service.getUserChallenges(user, filter, {
+ limit: PAGE_SIZE,
+ offset: page * PAGE_SIZE,
+ }).catch(() => ({ challenges: [] })));
+ }
+ return Promise.all(calls).then(([ch, uch]) => {
+ /* uch array contains challenges where the user is participating in
+ * some role. The same challenge are already listed in res array, but they
+ * are not attributed to the user there. This block of code marks user
+ * challenges in an efficient way. */
+ if (uch) {
+ const map = {};
+ uch.challenges.forEach((item) => { map[item.id] = item; });
+ ch.challenges.forEach((item) => {
+ if (map[item.id]) {
+ /* It is fine to reassing, as the array we modifying is created just
+ * above within the same function. */
+ /* eslint-disable no-param-reassign */
+ item.users[user] = true;
+ item.userDetails = map[item.id].userDetails;
+ /* eslint-enable no-param-reassign */
+ }
+ });
+ }
+
+ let { challenges, meta } = ch;
+ // filter by date range and re-compute meta
+ // we can safely remove the next two lines when backend support date range
+ challenges = filterUtil.filterByDate(challenges, frontFilter);
+ meta = filterUtil.newMeta(meta, challenges, frontFilter);
+ return {
+ uuid,
+ handle: tokenV3 ? user : null,
+ challenges,
+ meta,
+ frontFilter,
+ sort,
+ bucket,
+ tokenV3,
+ };
+ });
+}
+
+/**
+ * Init loading of all challenges
+ * @param {String} uuid
+ */
+function getRestActiveChallengesInit(uuid) {
+ return { uuid };
+}
+
+/**
+ * Loading all challenges
+ * @param {String} uuid
+ * @param {String} tokenV3
+ * @param {Object} backendFilter
+ * @param {Object} frontFilter
+ * @param {String} sort
+ * @param {String} bucket
+ */
+function getRestActiveChallengesDone(
+ uuid, tokenV3, backendFilter, frontFilter, sort, bucket,
+) {
+ const filter = processFilter({
+ ...backendFilter,
+ status: 'ACTIVE',
+ });
+
+ const service = getService(tokenV3);
+ const calls = [
+ getAll(params => service.getChallenges(filter, params), 1),
+ ];
+ let user;
+ if (tokenV3) {
+ user = decodeToken(tokenV3).handle;
+ calls.push(getAll(params => service.getUserChallenges(user, filter, params)
+ .catch(() => ({ challenges: [] }))), 1);
+ }
+ return Promise.all(calls).then(([ch, uch]) => {
+ /* uch array contains challenges where the user is participating in
+ * some role. The same challenge are already listed in res array, but they
+ * are not attributed to the user there. This block of code marks user
+ * challenges in an efficient way. */
+ if (uch) {
+ const map = {};
+ uch.challenges.forEach((item) => { map[item.id] = item; });
+ ch.challenges.forEach((item) => {
+ if (map[item.id]) {
+ /* It is fine to reassing, as the array we modifying is created just
+ * above within the same function. */
+ /* eslint-disable no-param-reassign */
+ item.users[user] = true;
+ item.userDetails = map[item.id].userDetails;
+ /* eslint-enable no-param-reassign */
+ }
+ });
+ }
+
+ let { challenges } = ch;
+ // filter by date range and re-compute meta
+ // we can safely remove the next two lines when backend support date range
+ challenges = filterUtil.filterByDate(challenges, frontFilter);
+ const meta = filterUtil.newMeta(undefined, challenges, frontFilter);
+
+ return {
+ uuid,
+ handle: tokenV3 ? user : null,
+ challenges,
+ frontFilter,
+ meta,
+ sort,
+ bucket,
+ };
+ });
+}
+
+/**
+ * Notifies the state that we are about to load the specified page of past
+ * challenges.
+ * @param {String} uuid
+ * @param {Number} page
+ * @param {Object} frontFilter
+ * @param {String} sort
+ * @return {Object}
+ */
+function getPastChallengesInit(uuid, page, frontFilter, sort) {
+ return {
+ uuid,
+ page,
+ frontFilter,
+ sort,
+ };
+}
+
+/**
+ * Gets the specified page of past challenges (including MMs).
+ * @param {String} uuid
+ * @param {Number} page Page of challenges to fetch.
+ * @param {Object} filter Backend filter to use.
+ * @param {String} tokenV3 Optional. Topcoder auth token v3.
+ * @param {Object} frontFilter Optional. Original frontend filter.
+ * @param {String} sort
+ * @return {Object}
+ */
+function getPastChallengesDone(uuid, page, filter, tokenV3, frontFilter = {}, sort) {
+ const service = getService(tokenV3);
+ const newFilter = processFilter({
+ ...filter,
+ status: 'COMPLETED',
+ });
+ return service.getChallenges(newFilter, {
+ limit: PAGE_SIZE,
+ offset: page * PAGE_SIZE,
+ }).then(({ challenges }) => ({
+ uuid,
+ challenges,
+ frontFilter,
+ sort,
+ }));
+}
+
+/**
+ * Action to get a list of currently open Review Opportunities using V3 API
+ * @param {String} uuid Unique identifier for init/donen instance from shortid module
+ * @param {Number} page Page of review opportunities to fetch.
+ * @param {String} tokenV3 Optional.
+ * @param {String} sort Optional.
+ * @param {Object} frontFilter Optional.
+ * @return {Object} Action object
+ */
+function getReviewOpportunitiesDone(uuid, page, tokenV3, sort, frontFilter = {}) {
+ return getReviewOpportunitiesService(tokenV3)
+ .getReviewOpportunities(REVIEW_OPPORTUNITY_PAGE_SIZE, page * REVIEW_OPPORTUNITY_PAGE_SIZE)
+ .then(loaded => ({
+ uuid, loaded, sort, frontFilter,
+ }))
+ .catch((error) => {
+ fireErrorMessage('Error Getting Review Opportunities', error.content || error);
+ return Promise.reject(error);
+ });
+}
+
+/**
+ * Payload creator for the action that inits the loading of SRMs.
+ * @param {String} uuid
+ * @return {String}
+ */
+function getSrmsInit(uuid) {
+ return uuid;
+}
+
+/**
+ * Payload creator for the action that loads SRMs.
+ * @param {String} uuid
+ * @param {String} handle
+ * @param {Object} params
+ * @param {String} tokenV3
+ */
+function getSrmsDone(uuid, handle, params, tokenV3) {
+ const service = getService(tokenV3);
+ const promises = [service.getSrms(params)];
+ if (handle) {
+ promises.push(service.getUserSrms(handle, params));
+ }
+ return Promise.all(promises).then((data) => {
+ let srms = data[0];
+ const userSrms = data[1];
+ const userSrmsMap = {};
+ _.forEach(userSrms, (srm) => {
+ userSrmsMap[srm.id] = srm;
+ });
+ srms = _.map(srms, (srm) => {
+ if (userSrmsMap[srm.id]) {
+ return processSRM(srm);
+ }
+ return srm;
+ });
+ return { uuid, data: srms };
+ });
+}
+
+export default createActions({
+ CHALLENGE_LISTING: {
+ DROP_CHALLENGES: bucket => ({ bucket }),
+
+ GET_MORE_CHALLENGES: bucket => ({ bucket }),
+
+ GET_ALL_ACTIVE_CHALLENGES_INIT: getAllActiveChallengesInit,
+ GET_ALL_ACTIVE_CHALLENGES_DONE: getAllActiveChallengesDone,
+
+ GET_ACTIVE_CHALLENGES_INIT: getActiveChallengesInit,
+ GET_ACTIVE_CHALLENGES_DONE: getActiveChallengesDone,
+
+ GET_REST_ACTIVE_CHALLENGES_INIT: getRestActiveChallengesInit,
+ GET_REST_ACTIVE_CHALLENGES_DONE: getRestActiveChallengesDone,
+
+ GET_CHALLENGE_SUBTRACKS_INIT: _.noop,
+ GET_CHALLENGE_SUBTRACKS_DONE: getChallengeSubtracksDone,
+
+ GET_CHALLENGE_TAGS_INIT: _.noop,
+ GET_CHALLENGE_TAGS_DONE: getChallengeTagsDone,
+
+ GET_PAST_CHALLENGES_INIT: getPastChallengesInit,
+ GET_PAST_CHALLENGES_DONE: getPastChallengesDone,
+
+ GET_REVIEW_OPPORTUNITIES_INIT: (uuid, page, sort) => ({ uuid, page, sort }),
+ GET_REVIEW_OPPORTUNITIES_DONE: getReviewOpportunitiesDone,
+
+ GET_SRMS_INIT: getSrmsInit,
+ GET_SRMS_DONE: getSrmsDone,
+
+ EXPAND_TAG: id => id,
+
+ /* Pass in community ID. */
+ SELECT_COMMUNITY: _.identity,
+
+ SET_FILTER: _.identity,
+
+ SET_DATEPICKER_STATUS: status => ({ status }),
+
+ SET_SORT: (bucket, sort) => ({ bucket, sort }),
+ },
+});
diff --git a/src/actions/index.js b/src/actions/index.js
index 8b1a241b..db1d6f66 100644
--- a/src/actions/index.js
+++ b/src/actions/index.js
@@ -13,6 +13,7 @@ import reviewOpportunityActions from './reviewOpportunity';
import lookupActions from './lookup';
import settingsActions from './settings';
import lookerActions from './looker';
+import challengeListingActions from './challenge-listing';
export const actions = {
auth: authActions.auth,
@@ -30,6 +31,7 @@ export const actions = {
lookup: lookupActions.lookup,
settings: settingsActions.settings,
looker: lookerActions.looker,
+ challengeListing: challengeListingActions.challengeListing,
};
export default undefined;
diff --git a/src/config/index.js b/src/config/index.js
new file mode 100644
index 00000000..2a5ab790
--- /dev/null
+++ b/src/config/index.js
@@ -0,0 +1,4 @@
+module.exports = {
+ PAGE_SIZE: 50,
+ REVIEW_OPPORTUNITY_PAGE_SIZE: 1000,
+};
diff --git a/src/index.js b/src/index.js
index a108716a..15b0e7d7 100644
--- a/src/index.js
+++ b/src/index.js
@@ -12,5 +12,5 @@ export { actions } from './actions';
export { services } from './services';
export {
- challenge, logger, errors, tc, time, mock,
+ challenge, logger, errors, tc, time, mock, url,
} from './utils';
diff --git a/src/reducers/challenge-listing.js b/src/reducers/challenge-listing.js
new file mode 100644
index 00000000..b1d87967
--- /dev/null
+++ b/src/reducers/challenge-listing.js
@@ -0,0 +1,848 @@
+/**
+ * Reducer for state.challengeListing.
+ */
+
+import _ from 'lodash';
+import { handleActions } from 'redux-actions';
+import moment from 'moment';
+import { updateQuery } from '../utils/url';
+import { SORTS_DATA } from '../utils/challenge/sort';
+import actions from '../actions/challenge-listing';
+import { logger, errors, challenge as challengeUtils } from '../utils';
+
+const { fireErrorMessage } = errors;
+const { filter: Filter } = challengeUtils;
+const { BUCKETS, BUCKET_DATA, getBuckets } = challengeUtils.buckets;
+
+/**
+ * Process challenge data for bucket
+ * @param handle user handle
+ * @param challenges all challenges
+ * @param loaded fetched challenges of bucket
+ * @param bucket bucket name
+ * @param sorts all sorts data
+ * @param sort sort name
+ * @param filter filter object
+ * @param frontFilter filter object
+ */
+function processBucketData(handle, challenges, loaded, bucket, sorts, sort, filter, frontFilter) {
+ const buckets = _.isEmpty(handle) ? BUCKET_DATA : getBuckets(handle);
+ const data = _.has(challenges, bucket) ? challenges[bucket]
+ .filter(filter)
+ .concat(loaded) : _.clone(loaded);
+
+ const finalFilters = {
+ ...frontFilter,
+ ...buckets[bucket].filter,
+ };
+
+ const bucketFilter = bucket !== BUCKETS.REVIEW_OPPORTUNITIES
+ ? Filter.getFilterFunction(finalFilters)
+ : Filter.getReviewOpportunitiesFilterFunction(finalFilters);
+ const filteredData = [];
+ for (let i = 0; i < data.length; i += 1) {
+ if (bucketFilter(data[i])) {
+ filteredData.push(data[i]);
+ }
+ }
+
+ if (bucket !== BUCKETS.ALL) {
+ if (!_.isEmpty(sort)) {
+ filteredData.sort(SORTS_DATA[sort].func);
+ return filteredData;
+ }
+
+ if (_.has(sorts, bucket)) {
+ filteredData.sort(SORTS_DATA[sorts[bucket]].func);
+ } else {
+ filteredData.sort(SORTS_DATA[BUCKET_DATA[bucket].sorts[0]].func);
+ }
+ }
+
+ return filteredData;
+}
+
+/**
+ * Check the challenges of bucket have been loaded all
+ * @param challenges all challenges
+ * @param bucket bucket name
+ * @param loaded loaded challenges this time
+ * @param data processed data
+ * @returns {boolean}
+ */
+function checkAllLoaded(challenges, bucket, loaded, data) {
+ let isAll = false;
+ if (loaded.length === 0) {
+ isAll = true;
+ } else if (!_.isEmpty(_.get(challenges, bucket))
+ && challenges[bucket].length === data.length) {
+ isAll = true;
+ }
+
+ return isAll;
+}
+
+/** TODO: Inspect if the 2 actions bellow can be removed?
+ * They do duplicate what is done in `getActiveChallengesDone` but fetch all challenges
+ * which was refactored in listing-improve
+ */
+function onGetAllActiveChallengesInit(state, { payload }) {
+ return { ...state, loadingActiveChallengesUUID: payload };
+}
+function onGetAllActiveChallengesDone(state, { error, payload }) {
+ if (error) {
+ logger.error(payload);
+ return state;
+ }
+ const { uuid, challenges: loaded } = payload;
+ if (uuid !== state.loadingActiveChallengesUUID) return state;
+ /* Once all active challenges are fetched from the API, we remove from the
+ * store any active challenges stored there previously, and also any
+ * challenges with IDs matching any challenges loaded now as active. */
+ const ids = new Set();
+ loaded.forEach(item => ids.add(item.id));
+ const challenges = state.challenges
+ .filter(item => item.status !== 'ACTIVE' && !ids.has(item.id))
+ .concat(loaded);
+
+ return {
+ ...state,
+ challenges,
+ lastUpdateOfActiveChallenges: Date.now(),
+ loadingActiveChallengesUUID: '',
+ };
+}
+
+/**
+ * Called when 1st page of ative challenges is loaded from `/challenges` api
+ * @param {*} state
+ * @param {*} param1
+ */
+function onGetActiveChallengesDone(state, { error, payload }) {
+ if (error) {
+ logger.error(payload);
+ return state;
+ }
+ const {
+ uuid, challenges: loaded, sort, bucket, tokenV3, handle, frontFilter,
+ meta,
+ } = payload;
+
+ /* Once all active challenges are fetched from the API, we remove from the
+ * store any active challenges stored there previously, and also any
+ * challenges with IDs matching any challenges loaded now as active. */
+ const ids = new Set();
+ loaded.forEach(item => ids.add(item.id));
+
+ let filter;
+ let newChallenges = {};
+ const otherState = {};
+ switch (bucket) {
+ case BUCKETS.ALL: {
+ if (uuid !== state.loadingActiveChallengesUUID) return state;
+ /* Fetching 0 page of active challenges also drops any active challenges
+ * loaded to the state before. */
+ filter = state.lastRequestedPageOfActiveChallenges
+ ? item => !ids.has(item.id)
+ : item => !ids.has(item.id) && item.status !== 'ACTIVE';
+
+ // my
+ const my = !_.isEmpty(tokenV3) ? processBucketData(
+ handle, state.challenges, loaded, BUCKETS.MY, state.sorts, sort, filter,
+ ) : [];
+ // open for registration
+ const open = processBucketData(
+ handle, state.challenges, loaded, BUCKETS.OPEN_FOR_REGISTRATION, state.sorts, sort, filter,
+ );
+ // ongoing
+ const ongoing = processBucketData(
+ handle, state.challenges, loaded, BUCKETS.ONGOING, state.sorts, sort, filter,
+ );
+ newChallenges = _.clone(state.challenges);
+ newChallenges[BUCKETS.MY] = my;
+ newChallenges[BUCKETS.OPEN_FOR_REGISTRATION] = open;
+ newChallenges[BUCKETS.ONGOING] = ongoing;
+ otherState.loadingActiveChallengesUUID = '';
+ otherState.meta = _.clone(meta);
+ }
+ break;
+ case BUCKETS.MY: {
+ if (uuid !== state.loadingMyChallengesUUID) return state;
+ /* Fetching 0 page of active challenges also drops any active challenges
+ * loaded to the state before. */
+ filter = state.lastRequestedPageOfMyChallenges
+ ? item => !ids.has(item.id)
+ : item => !ids.has(item.id) && item.status !== 'ACTIVE';
+
+ const data = processBucketData(
+ handle, state.challenges, loaded, bucket, state.sorts, sort, filter,
+ );
+ newChallenges = _.cloneDeep(state.challenges);
+ newChallenges[bucket] = data;
+ otherState.loadingMyChallengesUUID = '';
+ otherState.allMyChallengesLoaded = checkAllLoaded(state.challenges, bucket, loaded, data);
+ otherState.gettingMoreMyChallenges = !otherState.allMyChallengesLoaded;
+ otherState.meta = _.clone(meta);
+ /* TODO Due to the meta of backend response is currently not correct,
+/* so should update counts after fetch all challenges of bucket */
+ if (_.get(meta, 'myChallengesCount') !== data.length && otherState.allMyChallengesLoaded) {
+ otherState.meta.myChallengesCount = data.length;
+ otherState.meta.allChallengesCount = meta.allChallengesCount
+ + data.length - meta.myChallengesCount;
+ }
+ }
+ break;
+ case BUCKETS.OPEN_FOR_REGISTRATION: {
+ if (uuid !== state.loadingOpenChallengesUUID) return state;
+ /* Fetching 0 page of active challenges also drops any active challenges
+ * loaded to the state before. */
+ filter = state.lastRequestedPageOfOpenChallenges
+ ? item => !ids.has(item.id)
+ : item => !ids.has(item.id) && item.status !== 'ACTIVE';
+
+ const data = processBucketData(
+ handle, state.challenges, loaded, bucket, state.sorts, sort, filter,
+ );
+
+ newChallenges = _.cloneDeep(state.challenges);
+ newChallenges[bucket] = data;
+ otherState.loadingOpenChallengesUUID = '';
+ otherState.allOpenChallengesLoaded = checkAllLoaded(state.challenges, bucket, loaded, data);
+ otherState.gettingMoreOpenChallenges = !otherState.allOpenChallengesLoaded;
+ otherState.meta = _.clone(meta);
+ /* TODO Due to the meta of backend response is currently not correct,
+ /* so should update counts after fetch all challenges of bucket */
+ if (_.get(meta, 'openChallengesCount') !== data.length && otherState.allOpenChallengesLoaded) {
+ otherState.meta.openChallengesCount = data.length;
+ otherState.meta.allChallengesCount = meta.allChallengesCount
+ + data.length - meta.openChallengesCount;
+ }
+ }
+ break;
+ case BUCKETS.ONGOING: {
+ if (uuid !== state.loadingOnGoingChallengesUUID) return state;
+ /* Fetching 0 page of active challenges also drops any active challenges
+ * loaded to the state before. */
+ filter = state.lastRequestedPageOfOnGoingChallenges
+ ? item => !ids.has(item.id)
+ : item => !ids.has(item.id) && item.status !== 'ACTIVE';
+
+ const data = processBucketData(
+ handle, state.challenges, loaded, bucket, state.sorts, sort, filter,
+ );
+ newChallenges = _.cloneDeep(state.challenges);
+ newChallenges[bucket] = data;
+ otherState.loadingOnGoingChallengesUUID = '';
+ otherState.allOnGoingChallengesLoaded = checkAllLoaded(state.challenges,
+ bucket, loaded, data);
+ otherState.gettingMoreOnGoingChallenges = !otherState.allOnGoingChallengesLoaded;
+ /* TODO Due to the meta of backend response is currently not correct,
+ /* so should update counts after fetch all challenges of bucket */
+ otherState.meta = _.clone(meta);
+ if (_.get(meta, 'ongoingChallengesCount') !== data.length && otherState.allOnGoingChallengesLoaded) {
+ otherState.meta.ongoingChallengesCount = data.length;
+ otherState.meta.allChallengesCount = meta.allChallengesCount
+ + data.length - meta.ongoingChallengesCount;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ // all challenges used for other components like sub communities
+ newChallenges[BUCKETS.ALL] = processBucketData(
+ handle, state.challenges, loaded, BUCKETS.ALL, null, null, filter, frontFilter,
+ );
+
+ return {
+ ...state,
+ ...otherState,
+ challenges: newChallenges,
+ lastUpdateOfActiveChallenges: Date.now(),
+ };
+}
+
+/**
+ * Called when loading of 1st page of active challenges is started
+ * @param {*} state
+ * @param {*} param1
+ */
+function onGetActiveChallengesInit(state, { payload }) {
+ const { page, bucket, uuid } = payload;
+ const otherState = {};
+ switch (bucket) {
+ case BUCKETS.ALL:
+ otherState.loadingActiveChallengesUUID = uuid;
+ otherState.lastRequestedPageOfActiveChallenges = page;
+ break;
+ case BUCKETS.MY:
+ otherState.loadingMyChallengesUUID = uuid;
+ otherState.lastRequestedPageOfMyChallenges = page;
+ break;
+ case BUCKETS.OPEN_FOR_REGISTRATION:
+ otherState.loadingOpenChallengesUUID = uuid;
+ otherState.lastRequestedPageOfOpenChallenges = page;
+ break;
+ case BUCKETS.ONGOING:
+ otherState.loadingOnGoingChallengesUUID = uuid;
+ otherState.lastRequestedPageOfOnGoingChallenges = page;
+ break;
+ default:
+ break;
+ }
+
+ return {
+ ...state,
+ ...otherState,
+ };
+}
+function onGetRestActiveChallengesInit(state, { payload }) {
+ return {
+ ...state,
+ loadingRestActiveChallengesUUID: payload.uuid,
+ };
+}
+
+/**
+ * Called when all challenges are loaded
+ * @param {*} state
+ * @param {*} param1
+ */
+function onGetRestActiveChallengesDone(state, { error, payload }) {
+ if (error) {
+ logger.error(payload);
+ return state;
+ }
+ const {
+ uuid, challenges: loaded, meta: newMeta, sort, bucket, handle, frontFilter,
+ } = payload;
+ if (uuid !== state.loadingRestActiveChallengesUUID) return state;
+
+ /* Once all active challenges are fetched from the API, we remove from the
+ * store any active challenges stored there previously, and also any
+ * challenges with IDs matching any challenges loaded now as active. */
+ const ids = new Set();
+ loaded.forEach(item => ids.add(item.id));
+
+ /* Fetching 0 page of active challenges also drops any active challenges
+ * loaded to the state before. */
+ const filter = item => !ids.has(item.id);
+
+ const otherState = {};
+ let newChallenges = {};
+ switch (bucket) {
+ case BUCKETS.MY:
+ case BUCKETS.OPEN_FOR_REGISTRATION:
+ case BUCKETS.ONGOING: {
+ const data = processBucketData(
+ handle, state.challenges, loaded, bucket, state.sorts, sort, filter, frontFilter,
+ );
+ newChallenges = _.cloneDeep(state.challenges);
+ newChallenges[bucket] = data;
+ switch (bucket) {
+ case BUCKETS.MY:
+ otherState.allMyChallengesLoaded = true;
+ otherState.gettingMoreMyChallenges = false;
+ break;
+ case BUCKETS.OPEN_FOR_REGISTRATION:
+ otherState.allOpenChallengesLoaded = true;
+ otherState.gettingMoreOpenChallenges = false;
+ break;
+ case BUCKETS.ONGOING:
+ otherState.allOnGoingChallengesLoaded = true;
+ otherState.gettingMoreOnGoingChallenges = false;
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ const meta = newMeta || state.meta;
+
+ return {
+ ...state,
+ challenges: newChallenges,
+ ...otherState,
+ meta,
+ lastUpdateOfActiveChallenges: Date.now(),
+ lastRequestedPageOfActiveChallenges: -1,
+ loadingRestActiveChallengesUUID: '',
+ };
+}
+
+/**
+ * Handles CHALLENGE_LISTING/GET_CHALLENGE_SUBTRACKS_DONE action.
+ * @param {Object} state
+ * @param {Object} action
+ * @return {Object}
+ */
+function onGetChallengeSubtracksDone(state, action) {
+ if (action.error) logger.error(action.payload);
+ return {
+ ...state,
+ challengeSubtracks: action.error ? [] : action.payload,
+ challengeSubtracksMap: action.error ? {} : _.keyBy(action.payload, 'subTrack'),
+ loadingChallengeSubtracks: false,
+ };
+}
+
+/**
+ * Handles CHALLENGE_LISTING/GET_CHALLENGE_TAGS_DONE action.
+ * @param {Object} state
+ * @param {Object} action
+ * @return {Object}
+ */
+function onGetChallengeTagsDone(state, action) {
+ if (action.error) logger.error(action.payload);
+ return {
+ ...state,
+ challengeTags: action.error ? [] : action.payload,
+ loadingChallengeTags: false,
+ };
+}
+
+function onGetPastChallengesInit(state, action) {
+ const { frontFilter, page, uuid } = action.payload;
+ const tracks = frontFilter && frontFilter.tracks;
+ if (tracks && _.isEmpty(tracks)) {
+ return {
+ ...state,
+ allPastChallengesLoaded: true,
+ loadingPastChallengesUUID: '',
+ };
+ }
+
+ return {
+ ...state,
+ lastRequestedPageOfPastChallenges: page,
+ loadingPastChallengesUUID: uuid,
+ };
+}
+
+function onGetPastChallengesDone(state, { error, payload }) {
+ if (error) {
+ logger.error(payload);
+ return state;
+ }
+ const {
+ uuid, challenges: loaded, frontFilter, sort,
+ } = payload;
+ if (uuid !== state.loadingPastChallengesUUID) return state;
+
+ const ids = new Set();
+ loaded.forEach(item => ids.add(item.id));
+
+ /* Fetching 0 page of past challenges also drops any past challenges
+ * loaded to the state before. */
+ const filter = state.lastRequestedPageOfPastChallenges
+ ? item => !ids.has(item.id)
+ : item => !ids.has(item.id) && item.status !== 'COMPLETED' && item.status !== 'PAST';
+
+ const pasts = processBucketData(
+ null, state.challenges, loaded, BUCKETS.PAST, state.sorts, sort, filter, frontFilter,
+ );
+
+ let keepPastPlaceholders = false;
+ if (loaded.length) {
+ const ff = Filter.getFilterFunction(frontFilter);
+ keepPastPlaceholders = pasts.filter(ff).length
+ - (_.has(state.challenges, BUCKETS.PAST)
+ ? state.challenges[BUCKETS.PAST].filter(ff).length : 0) < 10;
+ }
+
+ const newChallenges = _.cloneDeep(state.challenges);
+ newChallenges[BUCKETS.PAST] = pasts;
+
+ return {
+ ...state,
+ allPastChallengesLoaded: loaded.length === 0,
+ challenges: newChallenges,
+ keepPastPlaceholders,
+ loadingPastChallengesUUID: '',
+ };
+}
+
+function onSelectCommunity(state, { payload }) {
+ updateQuery({ communityId: payload || undefined });
+ return {
+ ...state,
+ selectedCommunityId: payload,
+
+ /* Page numbers of past/upcoming challenges depend on the filters. To keep
+ * the code simple we just reset them each time a filter is modified.
+ * (This community selection defines community-specific filter for
+ * challenges). */
+ allPastChallengesLoaded: false,
+ lastRequestedPageOfPastChallenges: -1,
+ };
+}
+
+/**
+ * @param {Object} state
+ * @param {Object} action
+ * @return {Object}
+ */
+function onSetFilter(state, { payload }) {
+ /* Validation of filter parameters: they may come from URL query, thus
+ * validation is not a bad idea. As you may note, at the moment we do not
+ * do it very carefully (many params are not validated). */
+ const filter = _.clone(payload);
+ if (_.isPlainObject(filter.tags)) {
+ filter.tags = _.values(filter.tags);
+ }
+ if (_.isPlainObject(filter.subtracks)) {
+ filter.subtracks = _.values(filter.subtracks);
+ }
+ if (filter.startDate && !moment(filter.startDate).isValid()) {
+ delete filter.startDate;
+ }
+ if (filter.endDate && !moment(filter.endDate).isValid()) {
+ delete filter.endDate;
+ }
+
+ /* Update of URL and generation of the state. */
+ updateQuery({ filter });
+ return {
+ ...state,
+ filter,
+
+ /* Page numbers of past/upcoming challenges depend on the filters. To keep
+ * the code simple we just reset them each time a filter is modified. */
+ allPastChallengesLoaded: false,
+ lastRequestedPageOfPastChallenges: -1,
+ };
+}
+
+/**
+ * Handles CHALLENGE_LISTING/GET_REVIEW_OPPORTUNITIES_INIT action.
+ * @param {Object} state
+ * @param {Object} action Payload will be page, uuid
+ * @return {Object} New state
+ */
+function onGetReviewOpportunitiesInit(state, { payload }) {
+ return {
+ ...state,
+ lastRequestedPageOfReviewOpportunities: payload.page,
+ loadingReviewOpportunitiesUUID: payload.uuid,
+ };
+}
+
+/**
+ * Handles CHALLENGE_LISTING/GET_REVIEW_OPPORTUNITIES_DONE action.
+ * @param {Object} state
+ * @param {Object} action Payload will be JSON from api call and UUID
+ * @return {Object} New state
+ */
+function onGetReviewOpportunitiesDone(state, { payload, error }) {
+ if (error) {
+ return state;
+ }
+
+ const {
+ uuid,
+ loaded,
+ sort,
+ frontFilter,
+ } = payload;
+
+ if (uuid !== state.loadingReviewOpportunitiesUUID) return state;
+
+ const ids = new Set();
+ loaded.forEach(item => ids.add(item.id));
+
+ const filter = item => !ids.has(item.id);
+
+ const reviewOpportunities = processBucketData(
+ null, state, loaded, BUCKETS.REVIEW_OPPORTUNITIES,
+ state.sorts, sort, filter, frontFilter,
+ );
+
+ return {
+ ...state,
+ reviewOpportunities,
+ loadingReviewOpportunitiesUUID: '',
+ allReviewOpportunitiesLoaded: loaded.length === 0,
+ };
+}
+
+/**
+ * Inits the loading of SRMs.
+ * @param {Object} state
+ * @param {String} payload Operation UUID.
+ * @return {Object} New state.
+ */
+function onGetSrmsInit(state, { payload }) {
+ return {
+ ...state,
+ srms: {
+ ...state.srms,
+ loadingUuid: payload,
+ },
+ };
+}
+
+/**
+ * Handles loaded SRMs.
+ * @param {Object} state
+ * @param {Object} action
+ * @return {Object} New state.
+ */
+function onGetSrmsDone(state, { error, payload }) {
+ if (error) {
+ logger.error('Failed to load SRMs', payload);
+ fireErrorMessage('Failed to load SRMs', '');
+ return state;
+ }
+
+ const { uuid, data } = payload;
+ if (state.srms.loadingUuid !== uuid) return state;
+ return {
+ ...state,
+ srms: {
+ data,
+ loadingUuid: '',
+ timestamp: Date.now(),
+ },
+ };
+}
+
+/**
+ * Creates a new Challenge Listing reducer with the specified initial state.
+ * @param {Object} initialState Optional. Initial state.
+ * @return Challenge Listing reducer.
+ */
+function create(initialState) {
+ const a = actions.challengeListing;
+ return handleActions({
+ [a.dropChallenges]: (state, { payload }) => {
+ const { bucket } = payload;
+ const otherState = {};
+ switch (bucket) {
+ case BUCKETS.REVIEW_OPPORTUNITIES:
+ otherState.lastRequestedPageOfReviewOpportunities = -1;
+ otherState.reviewOpportunities = [];
+ otherState.allReviewOpportunitiesLoaded = false;
+ break;
+ case BUCKETS.PAST:
+ otherState.challenges = _.cloneDeep(state.challenges);
+ otherState.lastRequestedPageOfPastChallenges = -1;
+ otherState.challenges.past = [];
+ otherState.allPastChallengesLoaded = false;
+ break;
+ default:
+ otherState.challenges = {};
+ otherState.allMyChallengesLoaded = false;
+ otherState.allOnGoingChallengesLoaded = false;
+ otherState.allOpenChallengesLoaded = false;
+ otherState.allActiveChallengesLoaded = false;
+ otherState.allPastChallengesLoaded = false;
+ otherState.allReviewOpportunitiesLoaded = false;
+ otherState.lastRequestedPageOfActiveChallenges = -1;
+ otherState.lastRequestedPageOfMyChallenges = -1;
+ otherState.lastRequestedPageOfOpenChallenges = -1;
+ otherState.lastRequestedPageOfOnGoingChallenges = -1;
+ otherState.lastRequestedPageOfPastChallenges = -1;
+ otherState.lastRequestedPageOfReviewOpportunities = -1;
+ otherState.lastUpdateOfActiveChallenges = -1;
+ otherState.loadingActiveChallengesUUID = '';
+ otherState.loadingMyChallengesUUID = '';
+ otherState.loadingOpenChallengesUUID = '';
+ otherState.loadingOnGoingChallengesUUID = '';
+ otherState.loadingRestActiveChallengesUUID = '';
+ otherState.loadingPastChallengesUUID = '';
+ otherState.loadingReviewOpportunitiesUUID = '';
+ otherState.reviewOpportunities = [];
+ otherState.meta = {
+ allChallengesCount: 0,
+ myChallengesCount: 0,
+ ongoingChallengesCount: 0,
+ openChallengesCount: 0,
+ totalCount: 0,
+ };
+ break;
+ }
+
+ return ({
+ ...state,
+ ...otherState,
+ });
+ },
+
+ [a.getMoreChallenges]: (state, { payload }) => {
+ const { bucket } = payload;
+ const otherState = {};
+ switch (bucket) {
+ case BUCKETS.MY:
+ otherState.gettingMoreMyChallenges = true;
+ break;
+ case BUCKETS.ONGOING:
+ otherState.gettingMoreOnGoingChallenges = true;
+ break;
+ case BUCKETS.OPEN_FOR_REGISTRATION:
+ otherState.gettingMoreOpenChallenges = true;
+ break;
+ default:
+ break;
+ }
+ return ({
+ ...state,
+ ...otherState,
+ });
+ },
+
+ [a.expandTag]: (state, { payload }) => ({
+ ...state,
+ expandedTags: [...state.expandedTags, payload],
+ }),
+
+ [a.getAllActiveChallengesInit]: onGetAllActiveChallengesInit,
+ [a.getAllActiveChallengesDone]: onGetAllActiveChallengesDone,
+
+ [a.getActiveChallengesInit]: onGetActiveChallengesInit,
+ [a.getActiveChallengesDone]: onGetActiveChallengesDone,
+
+ [a.getRestActiveChallengesInit]: onGetRestActiveChallengesInit,
+ [a.getRestActiveChallengesDone]: onGetRestActiveChallengesDone,
+
+ [a.getChallengeSubtracksInit]: state => ({
+ ...state,
+ loadingChallengeSubtracks: true,
+ }),
+ [a.getChallengeSubtracksDone]: onGetChallengeSubtracksDone,
+
+ [a.getChallengeTagsInit]: state => ({
+ ...state,
+ loadingChallengeTags: true,
+ }),
+ [a.getChallengeTagsDone]: onGetChallengeTagsDone,
+
+ [a.getPastChallengesInit]: onGetPastChallengesInit,
+ [a.getPastChallengesDone]: onGetPastChallengesDone,
+
+ [a.getReviewOpportunitiesInit]: onGetReviewOpportunitiesInit,
+ [a.getReviewOpportunitiesDone]: onGetReviewOpportunitiesDone,
+
+ [a.getSrmsInit]: onGetSrmsInit,
+ [a.getSrmsDone]: onGetSrmsDone,
+
+ [a.selectCommunity]: onSelectCommunity,
+
+ [a.setFilter]: onSetFilter,
+ [a.setSort]: (state, { payload }) => {
+ const otherState = {};
+ switch (payload.bucket) {
+ case BUCKETS.PAST:
+ otherState.lastRequestedPageOfPastChallenges = -1;
+ break;
+ case BUCKETS.MY:
+ case BUCKETS.OPEN_FOR_REGISTRATION:
+ case BUCKETS.ONGOING:
+ otherState.lastRequestedPageOfActiveChallenges = -1;
+ break;
+ case BUCKETS.REVIEW_OPPORTUNITIES:
+ otherState.lastRequestedPageOfReviewOpportunities = -1;
+ break;
+ default:
+ break;
+ }
+ return ({
+ ...state,
+ ...otherState,
+ sorts: {
+ ...state.sorts,
+ [payload.bucket]: payload.sort,
+ },
+ });
+ },
+
+ [a.setDatePickerStatus]: (state, { payload }) => {
+ const { status } = payload;
+ return ({
+ ...state,
+ datepickerOpen: status,
+ });
+ },
+ }, _.defaults(_.clone(initialState) || {}, {
+ allMyChallengesLoaded: false,
+ allOnGoingChallengesLoaded: false,
+ allOpenChallengesLoaded: false,
+ allActiveChallengesLoaded: false,
+ allPastChallengesLoaded: false,
+ allReviewOpportunitiesLoaded: false,
+
+ challenges: {},
+ challengeSubtracks: [],
+ challengeSubtracksMap: {},
+ challengeTags: [],
+
+ expandedTags: [],
+
+ gettingMoreChallenges: false,
+ gettingMoreMyChallenges: false,
+ gettingMoreOnGoingChallenges: false,
+ gettingMoreOpenChallenges: false,
+
+ filter: {},
+
+ keepPastPlaceholders: false,
+
+ lastRequestedPageOfActiveChallenges: -1,
+ lastRequestedPageOfMyChallenges: -1,
+ lastRequestedPageOfOnGoingChallenges: -1,
+ lastRequestedPageOfOpenChallenges: -1,
+ lastRequestedPageOfPastChallenges: -1,
+ lastRequestedPageOfReviewOpportunities: -1,
+ lastUpdateOfActiveChallenges: 0,
+
+ loadingActiveChallengesUUID: '',
+ loadingMyChallengesUUID: '',
+ loadingOnGoingChallengesUUID: '',
+ loadingOpenChallengesUUID: '',
+ loadingRestActiveChallengesUUID: '',
+ loadingPastChallengesUUID: '',
+ loadingReviewOpportunitiesUUID: '',
+
+ loadingChallengeSubtracks: false,
+ loadingChallengeTags: false,
+
+ reviewOpportunities: [],
+
+ selectedCommunityId: '',
+
+ sorts: {},
+
+ srms: {
+ data: [],
+ loadingUuid: '',
+ timestamp: 0,
+ },
+
+ meta: {
+ allChallengesCount: 0,
+ myChallengesCount: 0,
+ ongoingChallengesCount: 0,
+ openChallengesCount: 0,
+ totalCount: 0,
+ },
+
+ datepickerOpen: false,
+ }));
+}
+
+/**
+ * The factory creates the new reducer with initial state tailored to the given
+ * ExpressJS HTTP request, if specified (for server-side rendering). If no HTTP
+ * request is specified, it creates the default reducer.
+ * @return {Promise} Resolves to the new reducer.
+ */
+export function factory() {
+ return Promise.resolve(create());
+}
+
+/* Default reducer with empty initial state. */
+export default create();
diff --git a/src/reducers/index.js b/src/reducers/index.js
index 15fd144c..aee34c61 100644
--- a/src/reducers/index.js
+++ b/src/reducers/index.js
@@ -22,6 +22,7 @@ import settings, { factory as settingsFactory }
from './settings';
import looker, { factory as lookerFactory }
from './looker';
+import challengeListing, { factory as challengeListingFactory } from './challenge-listing';
export function factory(options) {
@@ -41,6 +42,7 @@ export function factory(options) {
mySubmissionsManagement: mySubmissionsManagementFactory(options),
settings: settingsFactory(options),
looker: lookerFactory(options),
+ challengeListing: challengeListingFactory(options),
});
}
@@ -60,4 +62,5 @@ export default ({
mySubmissionsManagement,
settings,
looker,
+ challengeListing,
});
diff --git a/src/services/challenges.js b/src/services/challenges.js
index 604a2879..04244726 100644
--- a/src/services/challenges.js
+++ b/src/services/challenges.js
@@ -244,10 +244,10 @@ class ChallengesService {
params = {},
) => {
const query = {
- filter: qs.stringify(filters, { encode: false }),
+ filter: qs.stringify(filters, { encode: false }).replace('&', '%26'),
...params,
};
- const url = `${endpoint}?${qs.stringify(query)}`;
+ const url = `${endpoint}?${qs.stringify(query, { encode: false })}`;
const res = await this.private.api.get(url).then(checkError);
return {
challenges: res.content || [],
diff --git a/src/utils/challenge/buckets.js b/src/utils/challenge/buckets.js
new file mode 100644
index 00000000..d9e9221c
--- /dev/null
+++ b/src/utils/challenge/buckets.js
@@ -0,0 +1,153 @@
+/**
+ * Standard challenge buckets
+ */
+
+import _ from 'lodash';
+import { SORTS } from './sort';
+
+export const BUCKETS = {
+ ALL: 'all',
+ MY: 'my',
+ OPEN_FOR_REGISTRATION: 'openForRegistration',
+ ONGOING: 'ongoing',
+ PAST: 'past',
+ SAVED_FILTER: 'saved-filter',
+ UPCOMING: 'upcoming',
+ REVIEW_OPPORTUNITIES: 'reviewOpportunities',
+ SAVED_REVIEW_OPPORTUNITIES_FILTER: 'savedReviewOpportunitiesFilter',
+};
+
+export const BUCKET_DATA = {
+ [BUCKETS.ALL]: {
+ filter: {
+ started: true,
+ status: ['ACTIVE'],
+ },
+ hideCount: false,
+ name: 'All Challenges',
+ sorts: [],
+ },
+ [BUCKETS.MY]: {
+ filter: {
+ started: true,
+ status: ['ACTIVE'],
+ },
+ hideCount: false,
+ name: 'My Challenges',
+ sorts: [
+ SORTS.MOST_RECENT,
+ SORTS.TIME_TO_SUBMIT,
+ SORTS.NUM_REGISTRANTS,
+ SORTS.NUM_SUBMISSIONS,
+ SORTS.PRIZE_HIGH_TO_LOW,
+ SORTS.TITLE_A_TO_Z,
+ ],
+ },
+ [BUCKETS.OPEN_FOR_REGISTRATION]: {
+ filter: {
+ registrationOpen: true,
+ started: true,
+ status: ['ACTIVE'],
+ },
+ hideCount: false,
+ name: 'Open for registration',
+ sorts: [
+ SORTS.MOST_RECENT,
+ SORTS.TIME_TO_REGISTER,
+ SORTS.TIME_TO_SUBMIT,
+ SORTS.NUM_REGISTRANTS,
+ SORTS.NUM_SUBMISSIONS,
+ SORTS.PRIZE_HIGH_TO_LOW,
+ SORTS.TITLE_A_TO_Z,
+ ],
+ },
+ [BUCKETS.ONGOING]: {
+ filter: {
+ registrationOpen: false,
+ started: true,
+ status: ['ACTIVE'],
+ },
+ hideCount: false,
+ name: 'Ongoing challenges',
+ sorts: [
+ SORTS.MOST_RECENT,
+ SORTS.CURRENT_PHASE,
+ SORTS.TITLE_A_TO_Z,
+ SORTS.PRIZE_HIGH_TO_LOW,
+ ],
+ },
+ [BUCKETS.UPCOMING]: {
+ filter: {
+ upcoming: true,
+ },
+ hideCount: true,
+ name: 'Upcoming challenges',
+ sorts: [
+ SORTS.MOST_RECENT,
+ SORTS.PRIZE_HIGH_TO_LOW,
+ SORTS.TITLE_A_TO_Z,
+ ],
+ },
+ [BUCKETS.PAST]: {
+ filter: { status: ['COMPLETED', 'PAST'] },
+ hideCount: true,
+ name: 'Past challenges',
+ sorts: [
+ SORTS.MOST_RECENT,
+ SORTS.PRIZE_HIGH_TO_LOW,
+ SORTS.TITLE_A_TO_Z,
+ ],
+ },
+ [BUCKETS.REVIEW_OPPORTUNITIES]: {
+ filter: {},
+ hideCount: true,
+ name: 'Open for review',
+ sorts: [
+ SORTS.REVIEW_OPPORTUNITIES_START_DATE,
+ SORTS.REVIEW_OPPORTUNITIES_PAYMENT,
+ SORTS.REVIEW_OPPORTUNITIES_TITLE_A_TO_Z,
+ ],
+ },
+ [BUCKETS.SAVED_REVIEW_OPPORTUNITIES_FILTER]: {
+ filter: {},
+ sorts: [
+ SORTS.REVIEW_OPPORTUNITIES_START_DATE,
+ SORTS.REVIEW_OPPORTUNITIES_PAYMENT,
+ SORTS.REVIEW_OPPORTUNITIES_TITLE_A_TO_Z,
+ ],
+ },
+};
+
+/**
+ * Returns configuration of all possible challenge buckets.
+ * @param {String} userHandle Handle of the authenticated
+ * user to filter out My Challenges.
+ */
+export function getBuckets(userHandle) {
+ const res = _.cloneDeep(BUCKET_DATA);
+ res[BUCKETS.MY].filter.users = [userHandle];
+ return res;
+}
+
+/**
+ * Tests if a given bucket is of any of the Review Opportunities types
+ * @param {String} bucket The bucket in question
+ * @return {Boolean} True if the bucket contains Review Opportunities
+ */
+export const isReviewOpportunitiesBucket = bucket => (
+ bucket === BUCKETS.REVIEW_OPPORTUNITIES || bucket === BUCKETS.SAVED_REVIEW_OPPORTUNITIES_FILTER);
+
+/**
+ * Registers a new bucket.
+ * @param {String} id
+ * @param {Object} bucket
+ */
+export function registerBucket(id, bucket) {
+ if (BUCKET_DATA[id]) {
+ throw new Error('Bucket ID clush with an existing bucket');
+ }
+ BUCKETS[id] = id;
+ BUCKET_DATA[id] = bucket;
+}
+
+export default undefined;
diff --git a/src/utils/challenge/filter.js b/src/utils/challenge/filter.js
index 28e00654..bdd343af 100644
--- a/src/utils/challenge/filter.js
+++ b/src/utils/challenge/filter.js
@@ -177,6 +177,39 @@ function filterByUsers(challenge, state) {
return state.users.find(user => challenge.users[user]);
}
+/**
+ * [filterByDate filter challenges by date reange]
+ * @param {[type]} challenges input challenges
+ * @param {[type]} filter filter including startDate and endDate
+ * @return {[type]} filtered challenges array
+ */
+export function filterByDate(challenges, filter) {
+ let cs = challenges.filter(c => filterByStartDate(c, filter));
+ cs = cs.filter(c => filterByEndDate(c, filter));
+ return cs;
+}
+
+/**
+ * [newMeta compute new meta via challenges and filter]
+ * @param {[type]} meta old meta
+ * @param {[type]} challenges input challenges
+ * @param {[type]} filter filter including startDate and end endDate
+ * @return {[type]} new meta
+ */
+export function newMeta(meta, challenges, filter) {
+ if (!filter.startDate && !filter.endDate) {
+ return meta;
+ }
+ const m = {
+ };
+ m.allChallengesCount = challenges.length;
+ m.openChallengesCount = challenges.filter(c => c.registrationOpen === 'Yes').length;
+ m.ongoingChallengesCount = m.allChallengesCount - m.openChallengesCount;
+ m.myChallengesCount = challenges.filter(c => c.user && !_.isEmpty(c.user)).length;
+ m.totalCount = challenges.length;
+ return m;
+}
+
/**
* Returns clone of the state with the specified competition track added.
* @param {Object} state
diff --git a/src/utils/challenge/sort.js b/src/utils/challenge/sort.js
new file mode 100644
index 00000000..4091b0c0
--- /dev/null
+++ b/src/utils/challenge/sort.js
@@ -0,0 +1,84 @@
+/**
+ * Collection of compare function to sort challenges in different ways.
+ */
+
+import moment from 'moment';
+import { sumBy } from 'lodash';
+
+export const SORTS = {
+ CURRENT_PHASE: 'current-phase',
+ MOST_RECENT: 'most-recent',
+ NUM_REGISTRANTS: 'num-registrants',
+ NUM_SUBMISSIONS: 'num-submissions',
+ PRIZE_HIGH_TO_LOW: 'prize-high-to-low',
+ TIME_TO_REGISTER: 'time-to-register',
+ TIME_TO_SUBMIT: 'time-to-submit',
+ TITLE_A_TO_Z: 'title-a-to-z',
+ REVIEW_OPPORTUNITIES_TITLE_A_TO_Z: 'review-opportunities-title-a-to-z',
+ REVIEW_OPPORTUNITIES_PAYMENT: 'review-opportunities-payment',
+ REVIEW_OPPORTUNITIES_START_DATE: 'review-opportunities-start-date',
+};
+
+export const SORTS_DATA = {
+ [SORTS.CURRENT_PHASE]: {
+ func: (a, b) => a.status.localeCompare(b.status),
+ name: 'Current phase',
+ },
+ [SORTS.MOST_RECENT]: {
+ func: (a, b) => moment(b.registrationStartDate).diff(a.registrationStartDate),
+ name: 'Most recent',
+ },
+ [SORTS.NUM_REGISTRANTS]: {
+ func: (a, b) => b.numRegistrants - a.numRegistrants,
+ name: '# of registrants',
+ },
+ [SORTS.NUM_SUBMISSIONS]: {
+ func: (a, b) => b.numSubmissions - a.numSubmissions,
+ name: '# of submissions',
+ },
+ [SORTS.PRIZE_HIGH_TO_LOW]: {
+ func: (a, b) => b.totalPrize - a.totalPrize,
+ name: 'Prize high to low',
+ },
+ [SORTS.TIME_TO_REGISTER]: {
+ func: (a, b) => moment(a.registrationEndDate || a.submissionEndDate)
+ .diff(b.registrationEndDate || b.submissionEndDate),
+ name: 'Time to register',
+ },
+ [SORTS.TIME_TO_SUBMIT]: {
+ func: (a, b) => {
+ function nextSubEndDate(o) {
+ if (o.checkpointSubmissionEndDate && moment(o.checkpointSubmissionEndDate).isAfter()) {
+ return o.checkpointSubmissionEndDate;
+ }
+ return o.submissionEndDate;
+ }
+
+ const aDate = nextSubEndDate(a);
+ const bDate = nextSubEndDate(b);
+
+ if (moment(aDate).isBefore()) return 1;
+ if (moment(bDate).isBefore()) return -1;
+
+ return moment(aDate).diff(bDate);
+ },
+ name: 'Time to submit',
+ },
+ [SORTS.TITLE_A_TO_Z]: {
+ func: (a, b) => a.name.localeCompare(b.name),
+ name: 'Title A-Z',
+ },
+ [SORTS.REVIEW_OPPORTUNITIES_TITLE_A_TO_Z]: {
+ func: (a, b) => a.challenge.title.localeCompare(b.challenge.title),
+ name: 'Title A-Z',
+ },
+ [SORTS.REVIEW_OPPORTUNITIES_PAYMENT]: {
+ func: (a, b) => sumBy(b.payments, 'payment') - sumBy(a.payments, 'payment'),
+ name: 'Payment',
+ },
+ [SORTS.REVIEW_OPPORTUNITIES_START_DATE]: {
+ // This will implicitly use moment#valueOf
+ func: (a, b) => moment(a.startDate) - moment(b.startDate),
+ name: 'Review start date',
+ },
+};
diff --git a/src/utils/index.js b/src/utils/index.js
index b63d63b8..e7e4ff52 100644
--- a/src/utils/index.js
+++ b/src/utils/index.js
@@ -7,9 +7,14 @@ import * as time from './time';
import * as mock from './mock';
import * as errors from './errors';
import * as filter from './challenge/filter';
+import * as buckets from './challenge/buckets';
+import * as sort from './challenge/sort';
+import * as url from './url';
const challenge = {
filter,
+ buckets,
+ sort,
};
export {
@@ -19,4 +24,5 @@ export {
time,
mock,
errors,
+ url,
};
diff --git a/src/utils/tc.js b/src/utils/tc.js
index 77fce85a..08309d16 100644
--- a/src/utils/tc.js
+++ b/src/utils/tc.js
@@ -4,6 +4,9 @@
* @todo More TC-related utils should be moved here from Community-app.
*/
+import _ from 'lodash';
+import moment from 'moment';
+
/**
* Codes of the Topcoder communities.
*/
@@ -60,3 +63,47 @@ export async function getLookerApiResponsePayload(res) {
status: x.status,
};
}
+
+/**
+ * process srm to populate additional infomation
+ * adopt from topcoder-app repo
+ * @param {Object} s srm to process
+ * @return {Object} processed srm
+ */
+export function processSRM(s) {
+ const srm = _.cloneDeep(s);
+ srm.userStatus = 'registered';
+ if (Array.isArray(srm.rounds) && srm.rounds.length) {
+ if (srm.rounds[0].userSRMDetails && srm.rounds[0].userSRMDetails.rated) {
+ srm.result = srm.rounds[0].userSRMDetails;
+ }
+ if (srm.rounds[0].codingStartAt) {
+ srm.codingStartAt = srm.rounds[0].codingStartAt;
+ }
+ if (srm.rounds[0].codingEndAt) {
+ srm.codingEndAt = srm.rounds[0].codingEndAt;
+ }
+ if (srm.rounds[0].registrationStartAt) {
+ srm.registrationStartAt = srm.rounds[0].registrationStartAt;
+ }
+ if (srm.rounds[0].registrationEndAt) {
+ srm.registrationEndAt = srm.rounds[0].registrationEndAt;
+ }
+ }
+
+ // determines if the current phase is registration
+ let start = moment(srm.registrationStartAt).unix();
+ let end = moment(srm.registrationEndAt).unix();
+ let now = moment().unix();
+ if (start <= now && end >= now) {
+ srm.currentPhase = 'REGISTRATION';
+ }
+ // determines if the current phase is coding
+ start = moment(srm.codingStartAt).unix();
+ end = moment(srm.codingEndAt).unix();
+ now = moment().unix();
+ if (start <= now && end >= now) {
+ srm.currentPhase = 'CODING';
+ }
+ return srm;
+}
diff --git a/src/utils/url.js b/src/utils/url.js
new file mode 100644
index 00000000..73154aa7
--- /dev/null
+++ b/src/utils/url.js
@@ -0,0 +1,49 @@
+/**
+ * Various URL-related functions.
+ */
+
+/* global window */
+
+import _ from 'lodash';
+import qs from 'qs';
+import { isomorphy } from 'topcoder-react-utils';
+
+/**
+ * If executed client-side (determined in this case by the presence of global
+ * window object), this function updates query section of URL; otherwise does
+ * nothing.
+ * @param {Object} update Specifies the update to make. Current query will be
+ * parsed into JS object, then update will be merged into that object, and the
+ * result will be pushed back to the query section of URL. I.e. to unset some
+ * field of the query, that field should be explicitely mentioned inside
+ * 'update' as undefined.
+ */
+export function updateQuery(update) {
+ if (isomorphy.isServerSide()) return;
+
+ let query = qs.parse(window.location.search.slice(1));
+
+ /* _.merge won't work here, because it just ignores the fields explicitely
+ * set as undefined in the objects to be merged, rather than deleting such
+ * fields in the target object. */
+ _.forIn(update, (value, key) => {
+ if (_.isUndefined(value)) delete query[key];
+ else query[key] = value;
+ });
+ query = `?${qs.stringify(query, { encodeValuesOnly: true })}`;
+ window.history.replaceState(window.history.state, '', query);
+}
+
+/**
+ * Cleans/removes trailing slash from url
+ *
+ * @param {String} url The url to clean
+ * @return {String}
+ */
+export function removeTrailingSlash(url) {
+ return url.charAt(url.length - 1) === '/'
+ ? url.slice(0, -1)
+ : url;
+}
+
+export default undefined;
From c76aaa1ec7203a8ce2f709d3bc3ebb32cb6e8add Mon Sep 17 00:00:00 2001
From: Huan Li