MyFaces Core
  1. MyFaces Core
  2. MYFACES-2714

Include uncompressed jsf.js file and use it when development mode is used

    Details

    • Type: Improvement Improvement
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.0.0
    • Fix Version/s: 2.0.1
    • Component/s: JSR-314
    • Labels:
      None

      Description

      Reading some blogs about jsf 2.0, I notice mojarra include an uncompressed jsf.js file and use it when development mode is used. It is difficult to debug myfaces javascript for users and I think it is worth to do it too.

      1. MYFACES-2714-2.patch
        17 kB
        Leonardo Uribe
      2. MYFACES-2714-3.patch
        39 kB
        Leonardo Uribe
      3. MYFACES-2714-4.patch
        37 kB
        Leonardo Uribe
      4. MYFACES-2714-5.patch
        40 kB
        Leonardo Uribe
      5. MYFACES-2714-6.patch
        41 kB
        Leonardo Uribe

        Activity

        Leonardo Uribe made changes -
        Resolution Fixed [ 1 ]
        Status Reopened [ 4 ] Closed [ 6 ]
        Leonardo Uribe made changes -
        Resolution Fixed [ 1 ]
        Status Closed [ 6 ] Reopened [ 4 ]
        Hide
        Leonardo Uribe added a comment -

        Reopened because Werner found that use multiple files is only reliable on firefox. The solution is use a complete uncompressed jsf.js file and add a web config param called USE_MULTIPLE_JS_FILES_FOR_JSF_UNCOMPRESSED_JS

        Show
        Leonardo Uribe added a comment - Reopened because Werner found that use multiple files is only reliable on firefox. The solution is use a complete uncompressed jsf.js file and add a web config param called USE_MULTIPLE_JS_FILES_FOR_JSF_UNCOMPRESSED_JS
        Leonardo Uribe made changes -
        Status Resolved [ 5 ] Closed [ 6 ]
        Leonardo Uribe made changes -
        Fix Version/s 2.0.1 [ 12315117 ]
        Fix Version/s 2.0.1-SNAPSHOT [ 12314891 ]
        Leonardo Uribe made changes -
        Status Patch Available [ 10002 ] Resolved [ 5 ]
        Fix Version/s 2.0.1-SNAPSHOT [ 12314891 ]
        Resolution Fixed [ 1 ]
        Hide
        Leonardo Uribe added a comment -

        Thanks Werner for helping me with this issue

        Show
        Leonardo Uribe added a comment - Thanks Werner for helping me with this issue
        Hide
        Werner Punz added a comment -

        Ok I have to admit, I am an idiot, the method you just used is perfectly valid, only inline scripts are not evaled automatically by the browser if you work over innerHTML...

        I am going to submit the integration soon, I just renamed your method to loadScript and added a fallback mechanism just in case the browser prevents head alteration, and proper defer handling, so that everything should work across browsers.

        Show
        Werner Punz added a comment - Ok I have to admit, I am an idiot, the method you just used is perfectly valid, only inline scripts are not evaled automatically by the browser if you work over innerHTML... I am going to submit the integration soon, I just renamed your method to loadScript and added a fallback mechanism just in case the browser prevents head alteration, and proper defer handling, so that everything should work across browsers.
        Werner Punz made changes -
        Comment [ Ok Leo good news, I found a way to enable the proper eval handling without messing with firefoxes head.

          _this.globalEval(xhr.responseText + "\r\n//@ sourceURL=" + src);

        does the trick, that way you can tell firefox to reparse the original source url and use that one as source for all
        debugging needs, your dom head code now is obsolete, so far this works really well and is future proof.
        Since the old dom based code also only works on fox, I think this solution is better.

        ]
        Hide
        Leonardo Uribe added a comment -

        Ok, the code now it is committed.

        Show
        Leonardo Uribe added a comment - Ok, the code now it is committed.
        Hide
        Werner Punz added a comment -

        Ok Leo, lets do it that way simply commit your patches, I will work the little bit of changes on the js side into my optimized
        files and then I will recommit my code, that way we will be in sync again.
        I cannot commit my code today, since I have to run additional tests on the codebase before committing.
        The changes were substancial, which means thorough testing.

        Show
        Werner Punz added a comment - Ok Leo, lets do it that way simply commit your patches, I will work the little bit of changes on the js side into my optimized files and then I will recommit my code, that way we will be in sync again. I cannot commit my code today, since I have to run additional tests on the codebase before committing. The changes were substancial, which means thorough testing.
        Hide
        Leonardo Uribe added a comment -

        Hi Werner

        Yes, It could be great to add an eval fallback for the rest of the browsers.

        Show
        Leonardo Uribe added a comment - Hi Werner Yes, It could be great to add an eval fallback for the rest of the browsers.
        Hide
        Werner Punz added a comment -

        Hia Leonardo, sorry I was a few days on vacation, the method you mention here works only on firefoy and old ie5.5 browsers.
        It is fine with me if you add this functionality (btw. I will make another big commit tomorrow which reduces the overall compressed
        filesize by 10kb, I did some code optimizations while being on vacation)
        But you have to have in mind, that this will not work probably on all other browsers and might break on firefox too.
        That was the main reason why we did the whole code loading the way we did a global eval works on all browsers.

        But as I said, I am fine with it, but you have to be aware that this will only work in firebug
        (I can add an eval fallback for the rest of the browsers if you want)

        Show
        Werner Punz added a comment - Hia Leonardo, sorry I was a few days on vacation, the method you mention here works only on firefoy and old ie5.5 browsers. It is fine with me if you add this functionality (btw. I will make another big commit tomorrow which reduces the overall compressed filesize by 10kb, I did some code optimizations while being on vacation) But you have to have in mind, that this will not work probably on all other browsers and might break on firefox too. That was the main reason why we did the whole code loading the way we did a global eval works on all browsers. But as I said, I am fine with it, but you have to be aware that this will only work in firebug (I can add an eval fallback for the rest of the browsers if you want)
        Leonardo Uribe made changes -
        Attachment MYFACES-2714-6.patch [ 12445065 ]
        Hide
        Leonardo Uribe added a comment -

        I have attached a final version of the patch. I added an additional function on Runtime.js. That one makes my life easier debugging javascript!

        If no objections, I'll commit the patch soon.

        Show
        Leonardo Uribe added a comment - I have attached a final version of the patch. I added an additional function on Runtime.js. That one makes my life easier debugging javascript! If no objections, I'll commit the patch soon.
        Leonardo Uribe made changes -
        Attachment MYFACES-2714-5.patch [ 12445063 ]
        Hide
        Leonardo Uribe added a comment -

        Hi

        I did some tests with firebug, and I notice that if we add resources in this way:

        function oamLoadJavascript(resource)
        {
        var head = document.getElementsByTagName("head")[0];
        if ('undefined' == typeof head || null == head)

        { head = document.createElement("head"); head.appendChild(head); }

        var script = document.createElement("script");
        script.type = "text/javascript";
        script.src = resource;
        head.appendChild(script);
        }

        It works. Firebug recognize the resource as javascript and we can debug. Is it possible that someone with better knowledge on javascript refactor this function properly? After that, I'll update the patch and commit it.

        Show
        Leonardo Uribe added a comment - Hi I did some tests with firebug, and I notice that if we add resources in this way: function oamLoadJavascript(resource) { var head = document.getElementsByTagName("head") [0] ; if ('undefined' == typeof head || null == head) { head = document.createElement("head"); head.appendChild(head); } var script = document.createElement("script"); script.type = "text/javascript"; script.src = resource; head.appendChild(script); } It works. Firebug recognize the resource as javascript and we can debug. Is it possible that someone with better knowledge on javascript refactor this function properly? After that, I'll update the patch and commit it.
        Leonardo Uribe made changes -
        Attachment MYFACES-2714-4.patch [ 12444753 ]
        Hide
        Werner Punz added a comment -

        Ok I did a quick mockup of the loading mechanism
        it mostly works fine however firebug after the internal eval drops all carriage returns so that the scripts
        which are loaded that way are impossible to debug.
        So for now until I know the cause of this, I would recommend leos original approach
        of loading one big js file or making a set of direct include links.
        Nevertheless for testing here is my testcase

        <script type="text/javascript" src="#

        {resource['scripts:/myfaces/_impl/core/_Runtime.js']}

        "></script>
        <script type="text/javascript">
        myfaces._impl.core._Runtime.loadScript("#

        {resource['scripts:/myfaces/_impl/_util/_Lang.js']}

        ", null, null, "UTF-8");
        myfaces._impl.core._Runtime.loadScript("#

        {resource['scripts:/myfaces/_impl/_util/_Queue.js']}

        ", null, null, "UTF-8");
        myfaces._impl.core._Runtime.loadScript("#

        {resource['scripts:/myfaces/_impl/_util/_ListenerQueue.js']}

        ", null, null, "UTF-8");
        myfaces._impl.core._Runtime.loadScript("#

        {resource['scripts:/myfaces/_impl/_util/_Dom.js']}

        ", null, null, "UTF-8");
        myfaces._impl.core._Runtime.loadScript("#

        {resource['scripts:/myfaces/_impl/_util/_UnitTest.js']}

        ", null, null, "UTF-8");
        myfaces._impl.core._Runtime.loadScript("#

        {resource['scripts:/myfaces/_impl/_util/_HtmlStripper.js']}

        ", null, null, "UTF-8");
        myfaces._impl.core._Runtime.loadScript("#

        {resource['scripts:/myfaces/_impl/xhrCore/_AjaxUtils.js']}

        ", null, null, "UTF-8");
        myfaces._impl.core._Runtime.loadScript("#

        {resource['scripts:/myfaces/_impl/xhrCore/_AjaxRequestQueue.js']}

        ", null, null, "UTF-8");
        myfaces._impl.core._Runtime.loadScript("#

        {resource['scripts:/myfaces/_impl/xhrCore/_AjaxRequest.js']}

        ", null, null, "UTF-8");
        myfaces._impl.core._Runtime.loadScript("#

        {resource['scripts:/myfaces/_impl/xhrCore/_AjaxResponse.js']}

        ", null, null, "UTF-8");
        myfaces._impl.core._Runtime.loadScript("#

        {resource['scripts:/myfaces/_impl/xhrCore/_Transports.js']}

        ", null, null, "UTF-8");
        myfaces._impl.core._Runtime.loadScript("#

        {resource['scripts:/myfaces/_impl/core/Impl.js']}

        ", null, null, "UTF-8");
        myfaces._impl.core._Runtime.loadScript("#

        {resource['scripts:/myfaces/api/jsf.js']}

        ", null, null, "UTF-8");

        </script>

        Anyway unless I can resolve that carriage return issue, this approach at least for debugging porposes is not possible to use.

        Show
        Werner Punz added a comment - Ok I did a quick mockup of the loading mechanism it mostly works fine however firebug after the internal eval drops all carriage returns so that the scripts which are loaded that way are impossible to debug. So for now until I know the cause of this, I would recommend leos original approach of loading one big js file or making a set of direct include links. Nevertheless for testing here is my testcase <script type="text/javascript" src="# {resource['scripts:/myfaces/_impl/core/_Runtime.js']} "></script> <script type="text/javascript"> myfaces._impl.core._Runtime.loadScript("# {resource['scripts:/myfaces/_impl/_util/_Lang.js']} ", null, null, "UTF-8"); myfaces._impl.core._Runtime.loadScript("# {resource['scripts:/myfaces/_impl/_util/_Queue.js']} ", null, null, "UTF-8"); myfaces._impl.core._Runtime.loadScript("# {resource['scripts:/myfaces/_impl/_util/_ListenerQueue.js']} ", null, null, "UTF-8"); myfaces._impl.core._Runtime.loadScript("# {resource['scripts:/myfaces/_impl/_util/_Dom.js']} ", null, null, "UTF-8"); myfaces._impl.core._Runtime.loadScript("# {resource['scripts:/myfaces/_impl/_util/_UnitTest.js']} ", null, null, "UTF-8"); myfaces._impl.core._Runtime.loadScript("# {resource['scripts:/myfaces/_impl/_util/_HtmlStripper.js']} ", null, null, "UTF-8"); myfaces._impl.core._Runtime.loadScript("# {resource['scripts:/myfaces/_impl/xhrCore/_AjaxUtils.js']} ", null, null, "UTF-8"); myfaces._impl.core._Runtime.loadScript("# {resource['scripts:/myfaces/_impl/xhrCore/_AjaxRequestQueue.js']} ", null, null, "UTF-8"); myfaces._impl.core._Runtime.loadScript("# {resource['scripts:/myfaces/_impl/xhrCore/_AjaxRequest.js']} ", null, null, "UTF-8"); myfaces._impl.core._Runtime.loadScript("# {resource['scripts:/myfaces/_impl/xhrCore/_AjaxResponse.js']} ", null, null, "UTF-8"); myfaces._impl.core._Runtime.loadScript("# {resource['scripts:/myfaces/_impl/xhrCore/_Transports.js']} ", null, null, "UTF-8"); myfaces._impl.core._Runtime.loadScript("# {resource['scripts:/myfaces/_impl/core/Impl.js']} ", null, null, "UTF-8"); myfaces._impl.core._Runtime.loadScript("# {resource['scripts:/myfaces/api/jsf.js']} ", null, null, "UTF-8"); </script> Anyway unless I can resolve that carriage return issue, this approach at least for debugging porposes is not possible to use.
        Hide
        Werner Punz added a comment -

        hia leo...
        the refactoring for now is done, for the next few days there will be no change in the filestructure itself of our ajax core.

        The filestructure now is:

        <include>**/_impl/core/_Runtime.js</include>
        <include>**/_impl/_util/_Lang.js</include>
        <include>**/_impl/_util/_Queue.js</include>
        <include>**/_impl/_util/_ListenerQueue.js</include>
        <include>**/_impl/_util/_Dom.js</include>
        <include>**/_impl/_util/_HtmlStripper.js</include>
        <include>**/_impl/xhrCore/_AjaxUtils.js</include>
        <include>**/_impl/xhrCore/_AjaxRequestQueue.js</include>
        <include>**/_impl/xhrCore/_AjaxRequest.js</include>
        <include>**/_impl/xhrCore/_AjaxResponse.js</include>
        <include>**/_impl/xhrCore/_Transports.js</include>
        <include>**/_impl/core/Impl.js</include>
        <include>**/api/jsf.js</include>

        Show
        Werner Punz added a comment - hia leo... the refactoring for now is done, for the next few days there will be no change in the filestructure itself of our ajax core. The filestructure now is: <include>**/_impl/core/_Runtime.js</include> <include>**/_impl/_util/_Lang.js</include> <include>**/_impl/_util/_Queue.js</include> <include>**/_impl/_util/_ListenerQueue.js</include> <include>**/_impl/_util/_Dom.js</include> <include>**/_impl/_util/_HtmlStripper.js</include> <include>**/_impl/xhrCore/_AjaxUtils.js</include> <include>**/_impl/xhrCore/_AjaxRequestQueue.js</include> <include>**/_impl/xhrCore/_AjaxRequest.js</include> <include>**/_impl/xhrCore/_AjaxResponse.js</include> <include>**/_impl/xhrCore/_Transports.js</include> <include>**/_impl/core/Impl.js</include> <include>**/api/jsf.js</include>
        Hide
        Jan-Kees van Andel added a comment -

        Hi Leonardo,

        I don't see any issues, except two small ones:

        1 The SNAPSHOT dependency for the JS plugin

        2 The line: log.fine("Cannot evaluate EL expression "convertToExpression(expressionList) " in resource " + getLibraryName()+":"+getResourceName());
        looks like it "swallows" EL errors. I see that an event is published, but it looks like some information is lost in the event.
        Log.error might be more appropriate.

        But, I must admit, I have only looked at the code, I haven't tested it in a running application.

        I'm +1 on committing this patch.

        Show
        Jan-Kees van Andel added a comment - Hi Leonardo, I don't see any issues, except two small ones: 1 The SNAPSHOT dependency for the JS plugin 2 The line: log.fine("Cannot evaluate EL expression " convertToExpression(expressionList) " in resource " + getLibraryName()+":"+getResourceName()); looks like it "swallows" EL errors. I see that an event is published, but it looks like some information is lost in the event. Log.error might be more appropriate. But, I must admit, I have only looked at the code, I haven't tested it in a running application. I'm +1 on committing this patch.
        Hide
        Werner Punz added a comment - - edited

        Ok the patch looks fine except for the namespacing,
        our util etc... packages are marked as private hence the _ in the package names, they are missing.
        I am going to prototype this so please wait for my results, before adding it.

        Also I am currently in the middle of a refactoring, a file was added
        and another one changed, which I will commit today, Leo, you probably have to readjust the includes for that,
        or commit the patch and then let me do the readjustment.

        Show
        Werner Punz added a comment - - edited Ok the patch looks fine except for the namespacing, our util etc... packages are marked as private hence the _ in the package names, they are missing. I am going to prototype this so please wait for my results, before adding it. Also I am currently in the middle of a refactoring, a file was added and another one changed, which I will commit today, Leo, you probably have to readjust the includes for that, or commit the patch and then let me do the readjustment.
        Hide
        Jan-Kees van Andel added a comment -

        For archiving, this is the email conversation:

        ----------------------------------------------
        Jan-Kees van Andel aan MyFaces
        details weergeven 15 mei (2 dagen geleden)
        The plan sounds good, but let's not forget the performance penalty of loading multiple javascript files when in production mode. No objections for loading multiple files in development mode.

        Maybe, we should even (from a security perspective) completely deny access to the debug versions of the scripts when in production mode.

        My 2 cents...

        Regards,
        Jan-Kees

        ----------------------------------------------
        Michael Concini aan MyFaces
        details weergeven 15 mei (2 dagen geleden)
        I think Jan-Kees has a good point on denying access to the debug versions when in production mode. At least by default it might be good to deny access.

        ----------------------------------------------

        Definitely +1 from my side regarding this, debug versions
        should definitely be for development mode only.

        Werner

        ----------------------------------------------
        Hi

        I have attached a patch (MYFACES-2714-3.patch) that do what was suggested by Werner, including do not allow retrieve the javascript sources on production.

        Please, take a look at this one and if no objections, I'll commit the code.

        regards,

        Leonardo Uribe

        Show
        Jan-Kees van Andel added a comment - For archiving, this is the email conversation: ---------------------------------------------- Jan-Kees van Andel aan MyFaces details weergeven 15 mei (2 dagen geleden) The plan sounds good, but let's not forget the performance penalty of loading multiple javascript files when in production mode. No objections for loading multiple files in development mode. Maybe, we should even (from a security perspective) completely deny access to the debug versions of the scripts when in production mode. My 2 cents... Regards, Jan-Kees ---------------------------------------------- Michael Concini aan MyFaces details weergeven 15 mei (2 dagen geleden) I think Jan-Kees has a good point on denying access to the debug versions when in production mode. At least by default it might be good to deny access. ---------------------------------------------- Definitely +1 from my side regarding this, debug versions should definitely be for development mode only. Werner ---------------------------------------------- Hi I have attached a patch ( MYFACES-2714 -3.patch) that do what was suggested by Werner, including do not allow retrieve the javascript sources on production. Please, take a look at this one and if no objections, I'll commit the code. regards, Leonardo Uribe
        Leonardo Uribe made changes -
        Attachment MYFACES-2714-3.patch [ 12444619 ]
        Hide
        Werner Punz added a comment - - edited

        Actually lets do it step by step, first get Leos big combined file as debug file in, once I have ext-scripting 1.0 out (which is currently the next todo on
        my list) we
        can work on the other more fine grained solution, after all, there is no rush to do this.
        If anyone wants to start to work on this, feel free, after all this is opensource code, everyone can lay their hands on it.

        Anyway here is my idea how to solve that, what we need and what I am going to provided asap
        is auto dependency resolution, similar to dojo require or yuis namespace resolution.

        Hence once we have this working all which is needed is to include a single file which loads the runtime
        and then does a require to jsf.js) the rest should be done by the dependency resolution system.

        This should be fairly straight forward to implement since we already have most puzzle pieces in place like
        the namespace handling and the dynamic loading of javascript, it just needs the Runtime.require(<namespace>) glue in between and some additional attributes in the config for the charset the basepath and maybe a mapping scheme to make it compatible with the jsf resource loading.

        But as I said, let me get ext-scripting out of the door first, which I have postponed due to the more important fixes for jsf.js then we can tackle the auto dependency resolution for debugging mode.

        Show
        Werner Punz added a comment - - edited Actually lets do it step by step, first get Leos big combined file as debug file in, once I have ext-scripting 1.0 out (which is currently the next todo on my list) we can work on the other more fine grained solution, after all, there is no rush to do this. If anyone wants to start to work on this, feel free, after all this is opensource code, everyone can lay their hands on it. Anyway here is my idea how to solve that, what we need and what I am going to provided asap is auto dependency resolution, similar to dojo require or yuis namespace resolution. Hence once we have this working all which is needed is to include a single file which loads the runtime and then does a require to jsf.js) the rest should be done by the dependency resolution system. This should be fairly straight forward to implement since we already have most puzzle pieces in place like the namespace handling and the dynamic loading of javascript, it just needs the Runtime.require(<namespace>) glue in between and some additional attributes in the config for the charset the basepath and maybe a mapping scheme to make it compatible with the jsf resource loading. But as I said, let me get ext-scripting out of the door first, which I have postponed due to the more important fixes for jsf.js then we can tackle the auto dependency resolution for debugging mode.
        Hide
        Ganesh Jung added a comment -

        +1 on the Runtime.loadScript if you can get it to run. Else Leo's approach is helpful too.

        Show
        Ganesh Jung added a comment - +1 on the Runtime.loadScript if you can get it to run. Else Leo's approach is helpful too.
        Hide
        Werner Punz added a comment -

        No Objections from my side, but I would prefer an even better solution, since we are highly modular we could use
        the included xhr load functinality to load the scripts in dev mode one by one.

        The function which could be used theoretically would be
        myfaces._impl.core._Runtime.loadScript = function(src, type, defer, charSet):

        That however means that the myfaces._impl.core._Runtime must be loaded upfrond and then a series
        of myfaces._impl.core._Runtime.loadScript must be issued like following

        myfaces._impl.core._Runtime.loadScript("./myfaces/_util/_Lang.js", "text/javascript", false, "utf-8");
        myfaces._impl.core._Runtime.loadScript("./myfaces/_util/_Dom.js", "text/javascript", false, "utf-8");

        Not sure how the correct syntax for jsf resource requests is in that case

        So in the end a debug build just has to include the core and a loader file which issues the loadScript commands
        on the fly.

        That way we would not have a full single huge file which is hard to debug, but instead single files loaded dynamically.

        The other way would be to render the jsf.js files one by one in dev mode as separate includes.
        I would prefer a multi file include solution for dev purposes over the single file one, because it is easier to debug that way.

        Mojarra just includes one file because they are not modular (which if the codebase in this area grows will become a maintenance nightmare),
        since we do not have this nightmare why not be more modular in our includes as well?

        Show
        Werner Punz added a comment - No Objections from my side, but I would prefer an even better solution, since we are highly modular we could use the included xhr load functinality to load the scripts in dev mode one by one. The function which could be used theoretically would be myfaces._impl.core._Runtime.loadScript = function(src, type, defer, charSet): That however means that the myfaces._impl.core._Runtime must be loaded upfrond and then a series of myfaces._impl.core._Runtime.loadScript must be issued like following myfaces._impl.core._Runtime.loadScript("./myfaces/_util/_Lang.js", "text/javascript", false, "utf-8"); myfaces._impl.core._Runtime.loadScript("./myfaces/_util/_Dom.js", "text/javascript", false, "utf-8"); Not sure how the correct syntax for jsf resource requests is in that case So in the end a debug build just has to include the core and a loader file which issues the loadScript commands on the fly. That way we would not have a full single huge file which is hard to debug, but instead single files loaded dynamically. The other way would be to render the jsf.js files one by one in dev mode as separate includes. I would prefer a multi file include solution for dev purposes over the single file one, because it is easier to debug that way. Mojarra just includes one file because they are not modular (which if the codebase in this area grows will become a maintenance nightmare), since we do not have this nightmare why not be more modular in our includes as well?
        Hide
        Leonardo Uribe added a comment -

        If no objections, I'll commit this patch soon.

        Show
        Leonardo Uribe added a comment - If no objections, I'll commit this patch soon.
        Leonardo Uribe made changes -
        Status Open [ 1 ] Patch Available [ 10002 ]
        Leonardo Uribe made changes -
        Attachment MYFACES-2714-2.patch [ 12444534 ]
        Leonardo Uribe made changes -
        Attachment MYFACES-2714.patch [ 12444533 ]
        Leonardo Uribe made changes -
        Field Original Value New Value
        Attachment MYFACES-2714.patch [ 12444533 ]
        Leonardo Uribe created issue -

          People

          • Assignee:
            Leonardo Uribe
            Reporter:
            Leonardo Uribe
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development