!C99Shell v. 2.5 [PHP 8 Update] [24.05.2025]!

Software: Apache/2.4.41 (Ubuntu). PHP/8.0.30 

uname -a: Linux apirnd 5.4.0-204-generic #224-Ubuntu SMP Thu Dec 5 13:38:28 UTC 2024 x86_64 

uid=33(www-data) gid=33(www-data) groups=33(www-data) 

Safe-mode: OFF (not secure)

/var/www/html/node-red/packages/node_modules/@node-red/editor-client/src/js/ui/projects/   drwxr-xr-x
Free 13.09 GB of 57.97 GB (22.59%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Self remove    Logout    


Viewing file:     projects.js (141.68 KB)      -rwxr-xr-x
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/**
 * Copyright JS Foundation and other contributors, http://js.foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/
RED.projects = (function() {

    var dialog;
    var dialogBody;

    var activeProject;
    function reportUnexpectedError(error) {
        var notification;
        if (error.code === 'git_missing_user') {
            notification = RED.notify("<p>"+RED._("projects.errors.no-username-email")+"</p>",{
                fixed: true,
                type:'error',
                buttons: [
                    {
                        text: RED._("common.label.cancel"),
                        click: function() {
                            notification.close();
                        }
                    },
                    {
                        text: RED._("projects.config-git"),
                        click: function() {
                            RED.userSettings.show('gitconfig');
                            notification.close();
                        }
                    }
                ]
            })
        } else {
            console.log(error);
            notification = RED.notify("<p>"+RED._("projects.errors.unexpected")+":</p><p>"+error.message+"</p><small>"+RED._("projects.errors.code")+": "+error.code+"</small>",{
                fixed: true,
                modal: true,
                type: 'error',
                buttons: [
                    {
                        text: RED._("common.label.close"),
                        click: function() {
                            notification.close();
                        }
                    }
                ]
            })
        }
    }
    var screens = {};
    function initScreens() {
        var migrateProjectHeader = $('<div class="red-ui-projects-dialog-screen-start-hero"></div>');
        $('<span><i class="fa fa-files-o fa-2x"></i> &nbsp; &nbsp; <i class="fa fa-long-arrow-right fa-2x"></i> &nbsp; &nbsp; <i class="fa fa-archive fa-2x"></i></span>').appendTo(migrateProjectHeader)
        $('<hr>').appendTo(migrateProjectHeader);

        var createProjectOptions = {};

        screens = {
            'welcome': {
                content: function(options) {

                    var container = $('<div class="red-ui-projects-dialog-screen-start"></div>');

                    migrateProjectHeader.appendTo(container);

                    var body = $('<div class="red-ui-projects-dialog-screen-start-body"></div>').appendTo(container);
                    $('<p>').text(RED._("projects.welcome.hello")).appendTo(body);
                    $('<p>').text(RED._("projects.welcome.desc0")).appendTo(body);
                    $('<p>').text(RED._("projects.welcome.desc1")).appendTo(body);
                    $('<p>').text(RED._("projects.welcome.desc2")).appendTo(body);

                    var row = $('<div style="text-align: center"></div>').appendTo(body);
                    var createAsEmpty = $('<button data-type="empty" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-asterisk"></i><br/>'+RED._("projects.welcome.create")+'</button>').appendTo(row);
                    var createAsClone = $('<button data-type="clone" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-git"></i><br/>'+RED._("projects.welcome.clone")+'</button>').appendTo(row);

                    createAsEmpty.on("click", function(e) {
                        e.preventDefault();
                        createProjectOptions = {
                            action: "create"
                        }
                        show('git-config');
                    })

                    createAsClone.on("click", function(e) {
                        e.preventDefault();
                        createProjectOptions = {
                            action: "clone"
                        }
                        show('git-config');
                    })

                    return container;
                },
                buttons: [
                    {
                        // id: "red-ui-clipboard-dialog-cancel",
                        text: RED._("projects.welcome.openExistingProject"),
                        class: "secondary",
                        click: function() {
                            createProjectOptions = {
                                action: "open"
                            }
                            show('git-config');
                        }
                    },

                    {
                        // id: "red-ui-clipboard-dialog-cancel",
                        text: RED._("projects.welcome.not-right-now"),
                        click: function() {
                            createProjectOptions = {};
                            $( this ).dialog( "close" );
                        }
                    }
                ]
            },
            'git-config': (function() {
                var gitUsernameInput;
                var gitEmailInput;
                return {
                    content: function(options) {
                        var isGlobalConfig = false;
                        var existingGitSettings = RED.settings.get('git');
                        if (existingGitSettings && existingGitSettings.user) {
                            existingGitSettings = existingGitSettings.user;
                        } else if (RED.settings.git && RED.settings.git.globalUser) {
                            isGlobalConfig = true;
                            existingGitSettings = RED.settings.git.globalUser;
                        }

                        var validateForm = function() {
                            var name = gitUsernameInput.val().trim();
                            var email = gitEmailInput.val().trim();
                            var valid = name.length > 0 && email.length > 0;
                            $("#red-ui-projects-dialog-git-config").prop('disabled',!valid).toggleClass('disabled ui-button-disabled ui-state-disabled',!valid);

                        }

                        var container = $('<div class="red-ui-projects-dialog-screen-start"></div>');
                        migrateProjectHeader.appendTo(container);
                        var body = $('<div class="red-ui-projects-dialog-screen-start-body"></div>').appendTo(container);

                        $('<p>').text(RED._("projects.git-config.setup")).appendTo(body);
                        $('<p>').text(RED._("projects.git-config.desc0")).appendTo(body);
                        $('<p>').text(RED._("projects.git-config.desc1")).appendTo(body);

                        if (isGlobalConfig) {
                            $('<p>').text(RED._("projects.git-config.desc2")).appendTo(body);
                        }
                        $('<p>').text(RED._("projects.git-config.desc3")).appendTo(body);

                        var row = $('<div class="form-row"></div>').appendTo(body);
                        $('<label for="">'+RED._("projects.git-config.username")+'</label>').appendTo(row);
                        gitUsernameInput = $('<input type="text">').val((existingGitSettings&&existingGitSettings.name)||"").appendTo(row);
                        // $('<div style="position:relative;"></div>').text("This does not need to be your real name").appendTo(row);
                        gitUsernameInput.on("change keyup paste",validateForm);

                        row = $('<div class="form-row"></div>').appendTo(body);
                        $('<label for="">'+RED._("projects.git-config.email")+'</label>').appendTo(row);
                        gitEmailInput = $('<input type="text">').val((existingGitSettings&&existingGitSettings.email)||"").appendTo(row);
                        gitEmailInput.on("change keyup paste",validateForm);
                        // $('<div style="position:relative;"></div>').text("Something something email").appendTo(row);
                        setTimeout(function() {
                            gitUsernameInput.trigger("focus");
                            validateForm();
                        },50);
                        return container;
                    },
                    buttons: [
                        {
                            // id: "red-ui-clipboard-dialog-cancel",
                            text: RED._("common.label.back"),
                            click: function() {
                                show('welcome');
                            }
                        },
                        {
                            id: "red-ui-projects-dialog-git-config",
                            text: RED._("common.label.next"),
                            class: "primary",
                            click: function() {
                                var currentGitSettings = RED.settings.get('git') || {};
                                currentGitSettings.user = currentGitSettings.user || {};
                                currentGitSettings.user.name = gitUsernameInput.val();
                                currentGitSettings.user.email = gitEmailInput.val();
                                RED.settings.set('git', currentGitSettings);
                                if (createProjectOptions.action === "create") {
                                    show('project-details');
                                } else if (createProjectOptions.action === "clone") {
                                    show('clone-project');
                                } else if (createProjectOptions.action === "open") {
                                    show('create',{screen:'open'})
                                }
                            }
                        }
                    ]
                };
            })(),
            'project-details': (function() {
                var projectNameInput;
                var projectSummaryInput;
                return {
                    content: function(options) {
                        var projectList = null;
                        var projectNameValid;

                        var pendingFormValidation = false;
                        $.getJSON("projects", function(data) {
                            projectList = {};
                            data.projects.forEach(function(p) {
                                projectList[p] = true;
                                if (pendingFormValidation) {
                                    pendingFormValidation = false;
                                    validateForm();
                                }
                            })
                        });
                        var container = $('<div class="red-ui-projects-dialog-screen-start"></div>');
                        migrateProjectHeader.appendTo(container);
                        var body = $('<div class="red-ui-projects-dialog-screen-start-body"></div>').appendTo(container);

                        $('<p>').text(RED._("projects.project-details.create")).appendTo(body);
                        $('<p>').text(RED._("projects.project-details.desc0")).appendTo(body);
                        $('<p>').text(RED._("projects.project-details.desc1")).appendTo(body);
                        $('<p>').text(RED._("projects.project-details.desc2")).appendTo(body);

                        var validateForm = function() {
                            var projectName = projectNameInput.val();
                            var valid = true;
                            if (projectNameInputChanged) {
                                if (projectList === null) {
                                    pendingFormValidation = true;
                                    return;
                                }
                                projectNameStatus.empty();
                                if (!/^[a-zA-Z0-9\-_]+$/.test(projectName) || projectList[projectName]) {
                                    projectNameInput.addClass("input-error");
                                    $('<i style="margin-top: 8px;" class="fa fa-exclamation-triangle"></i>').appendTo(projectNameStatus);
                                    projectNameValid = false;
                                    valid = false;
                                    if (projectList[projectName]) {
                                        projectNameSublabel.text(RED._("projects.project-details.already-exists"));
                                    } else {
                                        projectNameSublabel.text(RED._("projects.project-details.must-contain"));
                                    }
                                } else {
                                    projectNameInput.removeClass("input-error");
                                    $('<i style="margin-top: 8px;" class="fa fa-check"></i>').appendTo(projectNameStatus);
                                    projectNameSublabel.text(RED._("projects.project-details.must-contain"));
                                    projectNameValid = true;
                                }
                                projectNameLastChecked = projectName;
                            }
                            valid = projectNameValid;
                            $("#red-ui-projects-dialog-create-name").prop('disabled',!valid).toggleClass('disabled ui-button-disabled ui-state-disabled',!valid);
                        }

                        var row = $('<div class="form-row"></div>').appendTo(body);
                        $('<label for="red-ui-projects-dialog-screen-create-project-name">'+RED._("projects.project-details.project-name")+'</label>').appendTo(row);

                        var subrow = $('<div style="position:relative;"></div>').appendTo(row);
                        projectNameInput = $('<input id="red-ui-projects-dialog-screen-create-project-name" type="text"></input>').val(createProjectOptions.name||"").appendTo(subrow);
                        var projectNameStatus = $('<div class="red-ui-projects-dialog-screen-input-status"></div>').appendTo(subrow);

                        var projectNameInputChanged = false;
                        var projectNameLastChecked = "";
                        var projectNameValid;
                        var checkProjectName;
                        var autoInsertedName = "";


                        projectNameInput.on("change keyup paste",function() {
                            projectNameInputChanged = (projectNameInput.val() !== projectNameLastChecked);
                            if (checkProjectName) {
                                clearTimeout(checkProjectName);
                            } else if (projectNameInputChanged) {
                                projectNameStatus.empty();
                                $('<img src="red/images/spin.svg"/>').appendTo(projectNameStatus);
                                if (projectNameInput.val() === '') {
                                    validateForm();
                                    return;
                                }
                            }
                            checkProjectName = setTimeout(function() {
                                validateForm();
                                checkProjectName = null;
                            },300)
                        });
                        projectNameSublabel = $('<label class="red-ui-projects-edit-form-sublabel"><small>'+RED._("projects.project-details.must-contain")+'</small></label>').appendTo(row).find("small");

                        // Empty Project
                        row = $('<div class="form-row red-ui-projects-dialog-screen-create-row red-ui-projects-dialog-screen-create-row-empty"></div>').appendTo(body);
                        $('<label for="red-ui-projects-dialog-screen-create-project-desc">'+RED._("projects.project-details.desc")+'</label>').appendTo(row);
                        projectSummaryInput = $('<input id="red-ui-projects-dialog-screen-create-project-desc" type="text">').val(createProjectOptions.summary||"").appendTo(row);
                        $('<label class="red-ui-projects-edit-form-sublabel"><small>'+RED._("projects.project-details.opt")+'</small></label>').appendTo(row);

                        setTimeout(function() {
                            projectNameInput.trigger("focus");
                            projectNameInput.trigger("change");
                        },50);
                        return container;
                    },
                    buttons: function(options) {
                        return [
                            {
                                text: RED._("common.label.back"),
                                click: function() {
                                    show('git-config');
                                }
                            },
                            {
                                id: "red-ui-projects-dialog-create-name",
                                disabled: true,
                                text: RED._("common.label.next"),
                                class: "primary disabled",
                                click: function() {
                                    createProjectOptions.name = projectNameInput.val();
                                    createProjectOptions.summary = projectSummaryInput.val();
                                    show('default-files', options);
                                }
                            }
                        ]
                    }
                };
            })(),
            'clone-project': (function() {
                var projectNameInput;
                var projectSummaryInput;
                var projectFlowFileInput;
                var projectSecretInput;
                var projectSecretSelect;
                var copyProject;
                var projectRepoInput;
                var projectCloneSecret;
                var emptyProjectCredentialInput;
                var projectRepoUserInput;
                var projectRepoPasswordInput;
                var projectNameSublabel;
                var projectRepoSSHKeySelect;
                var projectRepoPassphrase;
                var projectRepoRemoteName
                var projectRepoBranch;
                var selectedProject;

                return {
                    content: function(options) {
                        var container = $('<div class="red-ui-projects-dialog-screen-start"></div>');
                        migrateProjectHeader.appendTo(container);
                        var body = $('<div class="red-ui-projects-dialog-screen-start-body"></div>').appendTo(container);
                        $('<p>').text(RED._("projects.clone-project.clone")).appendTo(body);
                        $('<p>').text(RED._("projects.clone-project.desc0")).appendTo(body);

                        var projectList = null;
                        var pendingFormValidation = false;
                        $.getJSON("projects", function(data) {
                            projectList = {};
                            data.projects.forEach(function(p) {
                                projectList[p] = true;
                                if (pendingFormValidation) {
                                    pendingFormValidation = false;
                                    validateForm();
                                }
                            })
                        });


                        var validateForm = function() {
                            var projectName = projectNameInput.val();
                            var valid = true;
                            if (projectNameInputChanged) {
                                if (projectList === null) {
                                    pendingFormValidation = true;
                                    return;
                                }
                                projectNameStatus.empty();
                                if (!/^[a-zA-Z0-9\-_]+$/.test(projectName) || projectList[projectName]) {
                                    projectNameInput.addClass("input-error");
                                    $('<i style="margin-top: 8px;" class="fa fa-exclamation-triangle"></i>').appendTo(projectNameStatus);
                                    projectNameValid = false;
                                    valid = false;
                                    if (projectList[projectName]) {
                                        projectNameSublabel.text(RED._("projects.clone-project.already-exists"));
                                    } else {
                                        projectNameSublabel.text(RED._("projects.clone-project.must-contain"));
                                    }
                                } else {
                                    projectNameInput.removeClass("input-error");
                                    $('<i style="margin-top: 8px;" class="fa fa-check"></i>').appendTo(projectNameStatus);
                                    projectNameSublabel.text(RED._("projects.clone-project.must-contain"));
                                    projectNameValid = true;
                                }
                                projectNameLastChecked = projectName;
                            }
                            valid = projectNameValid;

                            var repo = projectRepoInput.val();

                            // var validRepo = /^(?:file|git|ssh|https?|[\d\w\.\-_]+@[\w\.]+):(?:\/\/)?[\w\.@:\/~_-]+(?:\/?|\#[\d\w\.\-_]+?)$/.test(repo);
                            var validRepo = repo.length > 0 && !/\s/.test(repo);
                            if (/^https?:\/\/[^/]+@/i.test(repo)) {
                                $("#red-ui-projects-dialog-screen-create-project-repo-label small").text(RED._("projects.clone-project.no-info-in-url"));
                                validRepo = false;
                            }
                            if (!validRepo) {
                                if (projectRepoChanged) {
                                    projectRepoInput.addClass("input-error");
                                }
                                valid = false;
                            } else {
                                projectRepoInput.removeClass("input-error");
                            }
                            if (/^https?:\/\//.test(repo)) {
                                $(".red-ui-projects-dialog-screen-create-row-creds").show();
                                $(".red-ui-projects-dialog-screen-create-row-sshkey").hide();
                            } else if (/^(?:ssh|[\S]+?@[\S]+?):(?:\/\/)?/.test(repo)) {
                                $(".red-ui-projects-dialog-screen-create-row-creds").hide();
                                $(".red-ui-projects-dialog-screen-create-row-sshkey").show();
                                // if ( !getSelectedSSHKey(projectRepoSSHKeySelect) ) {
                                //     valid = false;
                                // }
                            } else {
                                $(".red-ui-projects-dialog-screen-create-row-creds").hide();
                                $(".red-ui-projects-dialog-screen-create-row-sshkey").hide();
                            }

                            $("#red-ui-projects-dialog-clone-project").prop('disabled',!valid).toggleClass('disabled ui-button-disabled ui-state-disabled',!valid);
                        }

                        var row;

                        row = $('<div class="form-row red-ui-projects-dialog-screen-create-row red-ui-projects-dialog-screen-create-row-empty red-ui-projects-dialog-screen-create-row-clone"></div>').appendTo(body);
                        $('<label for="red-ui-projects-dialog-screen-create-project-name">'+RED._("projects.clone-project.project-name")+'</label>').appendTo(row);

                        var subrow = $('<div style="position:relative;"></div>').appendTo(row);
                        projectNameInput = $('<input id="red-ui-projects-dialog-screen-create-project-name" type="text"></input>').appendTo(subrow);
                        var projectNameStatus = $('<div class="red-ui-projects-dialog-screen-input-status"></div>').appendTo(subrow);

                        var projectNameInputChanged = false;
                        var projectNameLastChecked = "";
                        var projectNameValid;
                        var checkProjectName;
                        var autoInsertedName = "";


                        projectNameInput.on("change keyup paste",function() {
                            projectNameInputChanged = (projectNameInput.val() !== projectNameLastChecked);
                            if (checkProjectName) {
                                clearTimeout(checkProjectName);
                            } else if (projectNameInputChanged) {
                                projectNameStatus.empty();
                                $('<img src="red/images/spin.svg"/>').appendTo(projectNameStatus);
                                if (projectNameInput.val() === '') {
                                    validateForm();
                                    return;
                                }
                            }
                            checkProjectName = setTimeout(function() {
                                validateForm();
                                checkProjectName = null;
                            },300)
                        });
                        projectNameSublabel = $('<label class="red-ui-projects-edit-form-sublabel"><small>'+RED._("projects.clone-project.must-contain")+'</small></label>').appendTo(row).find("small");

                        row = $('<div class="form-row red-ui-projects-dialog-screen-create-row red-ui-projects-dialog-screen-create-row-clone"></div>').appendTo(body);
                        $('<label for="red-ui-projects-dialog-screen-create-project-repo">'+RED._("projects.clone-project.git-url")+'</label>').appendTo(row);
                        projectRepoInput = $('<input id="red-ui-projects-dialog-screen-create-project-repo" type="text" placeholder="https://git.example.com/path/my-project.git"></input>').appendTo(row);
                        $('<label id="red-ui-projects-dialog-screen-create-project-repo-label" class="red-ui-projects-edit-form-sublabel"><small>'+RED._("projects.clone-project.protocols")+'</small></label>').appendTo(row);
                        var projectRepoChanged = false;
                        var lastProjectRepo = "";
                        projectRepoInput.on("change keyup paste",function() {
                            projectRepoChanged = true;
                            var repo = $(this).val();
                            if (lastProjectRepo !== repo) {
                                $("#red-ui-projects-dialog-screen-create-project-repo-label small").text(RED._("projects.clone-project.protocols"));
                            }
                            lastProjectRepo = repo;

                            var m = /\/([^/]+?)(?:\.git)?$/.exec(repo);
                            if (m) {
                                var projectName = projectNameInput.val();
                                if (projectName === "" || projectName === autoInsertedName) {
                                    autoInsertedName = m[1];
                                    projectNameInput.val(autoInsertedName);
                                    projectNameInput.trigger("change");
                                }
                            }
                            validateForm();
                        });

                        var cloneAuthRows = $('<div class="red-ui-projects-dialog-screen-create-row"></div>').appendTo(body);
                        row = $('<div class="form-row red-ui-projects-dialog-screen-create-row-auth-error"></div>').hide().appendTo(cloneAuthRows);
                        $('<div><i class="fa fa-warning"></i> '+RED._("projects.clone-project.auth-failed")+'</div>').appendTo(row);

                        // Repo credentials - username/password ----------------
                        row = $('<div class="hide form-row red-ui-projects-dialog-screen-create-row-creds"></div>').hide().appendTo(cloneAuthRows);

                        var subrow = $('<div style="width: calc(50% - 10px); display:inline-block;"></div>').appendTo(row);
                        $('<label for="red-ui-projects-dialog-screen-create-project-repo-user">'+RED._("projects.clone-project.username")+'</label>').appendTo(subrow);
                        projectRepoUserInput = $('<input id="red-ui-projects-dialog-screen-create-project-repo-user" type="text"></input>').appendTo(subrow);

                        subrow = $('<div style="width: calc(50% - 10px); margin-left: 20px; display:inline-block;"></div>').appendTo(row);
                        $('<label for="red-ui-projects-dialog-screen-create-project-repo-pass">'+RED._("projects.clone-project.passwd")+'</label>').appendTo(subrow);
                        projectRepoPasswordInput = $('<input style="width:100%" id="red-ui-projects-dialog-screen-create-project-repo-pass" type="password"></input>').appendTo(subrow);
                        projectRepoPasswordInput.typedInput({type:"cred"});
                        // -----------------------------------------------------

                        // Repo credentials - key/passphrase -------------------
                        row = $('<div class="form-row red-ui-projects-dialog-screen-create-row red-ui-projects-dialog-screen-create-row-sshkey"></div>').hide().appendTo(cloneAuthRows);
                        subrow = $('<div style="width: calc(50% - 10px); display:inline-block;"></div>').appendTo(row);
                        $('<label for="red-ui-projects-dialog-screen-create-project-repo-passphrase">'+RED._("projects.clone-project.ssh-key")+'</label>').appendTo(subrow);
                        projectRepoSSHKeySelect = $("<select>",{style:"width: 100%"}).appendTo(subrow);

                        $.getJSON("settings/user/keys", function(data) {
                            var count = 0;
                            data.keys.forEach(function(key) {
                                projectRepoSSHKeySelect.append($("<option></option>").val(key.name).text(key.name));
                                count++;
                            });
                            if (count === 0) {
                                projectRepoSSHKeySelect.addClass("input-error");
                                projectRepoSSHKeySelect.attr("disabled",true);
                                sshwarningRow.show();
                            } else {
                                projectRepoSSHKeySelect.removeClass("input-error");
                                projectRepoSSHKeySelect.attr("disabled",false);
                                sshwarningRow.hide();
                            }
                        });
                        subrow = $('<div style="width: calc(50% - 10px); margin-left: 20px; display:inline-block;"></div>').appendTo(row);
                        $('<label for="red-ui-projects-dialog-screen-create-project-repo-passphrase">'+RED._("projects.clone-project.passphrase")+'</label>').appendTo(subrow);
                        projectRepoPassphrase = $('<input id="red-ui-projects-dialog-screen-create-project-repo-passphrase" type="password"></input>').appendTo(subrow);
                        projectRepoPassphrase.typedInput({type:"cred"});
                        subrow = $('<div class="form-row red-ui-projects-dialog-screen-create-row red-ui-projects-dialog-screen-create-row-sshkey"></div>').appendTo(cloneAuthRows);
                        var sshwarningRow = $('<div class="red-ui-projects-dialog-screen-create-row-auth-error-no-keys"></div>').hide().appendTo(subrow);
                        $('<div class="form-row"><i class="fa fa-warning"></i> '+RED._("projects.clone-project.ssh-key-desc")+'</div>').appendTo(sshwarningRow);
                        subrow = $('<div style="text-align: center">').appendTo(sshwarningRow);
                        $('<button class="red-ui-button red-ui-projects-dialog-button">'+RED._("projects.clone-project.ssh-key-add")+'</button>').appendTo(subrow).on("click", function(e) {
                            e.preventDefault();
                            dialog.dialog( "close" );
                            RED.userSettings.show('gitconfig');
                            setTimeout(function() {
                                $("#user-settings-gitconfig-add-key").trigger("click");
                            },500);
                        });
                        // -----------------------------------------------------


                        // Secret - clone
                        row = $('<div class="form-row red-ui-projects-dialog-screen-create-row red-ui-projects-dialog-screen-create-row-clone"></div>').appendTo(body);
                        $('<label>'+RED._("projects.clone-project.credential-key")+'</label>').appendTo(row);
                        projectSecretInput = $('<input style="width: 100%" type="password"></input>').appendTo(row);
                        projectSecretInput.typedInput({type:"cred"});


                        return container;
                    },
                    buttons: function(options) {
                        return [
                            {
                                text: RED._("common.label.back"),
                                click: function() {
                                    show('git-config');
                                }
                            },
                            {
                                id: "red-ui-projects-dialog-clone-project",
                                disabled: true,
                                text: RED._("common.label.clone"),
                                class: "primary disabled",
                                click: function() {
                                    var projectType = $(".red-ui-projects-dialog-screen-create-type.selected").data('type');
                                    var projectData = {
                                        name: projectNameInput.val(),
                                    }
                                    projectData.credentialSecret = projectSecretInput.val();
                                    var repoUrl = projectRepoInput.val();
                                    var metaData = {};
                                    if (/^(?:ssh|[\d\w\.\-_]+@[\w\.]+):(?:\/\/)?/.test(repoUrl)) {
                                        var selected = projectRepoSSHKeySelect.val();//false;//getSelectedSSHKey(projectRepoSSHKeySelect);
                                        if ( selected ) {
                                            projectData.git = {
                                                remotes: {
                                                    'origin': {
                                                        url: repoUrl,
                                                        keyFile: selected,
                                                        passphrase: projectRepoPassphrase.val()
                                                    }
                                                }
                                            };
                                        }
                                        else {
                                            console.log(RED._("projects.clone-project.cant-get-ssh-key"));
                                            return;
                                        }
                                    }
                                    else {
                                        projectData.git = {
                                            remotes: {
                                                'origin': {
                                                    url: repoUrl,
                                                    username: projectRepoUserInput.val(),
                                                    password: projectRepoPasswordInput.val()
                                                }
                                            }
                                        };
                                    }

                                    $(".red-ui-projects-dialog-screen-create-row-auth-error").hide();
                                    $("#red-ui-projects-dialog-screen-create-project-repo-label small").text(RED._("projects.clone-project.protocols"));

                                    projectRepoUserInput.removeClass("input-error");
                                    projectRepoPasswordInput.removeClass("input-error");
                                    projectRepoSSHKeySelect.removeClass("input-error");
                                    projectRepoPassphrase.removeClass("input-error");

                                    RED.deploy.setDeployInflight(true);
                                    RED.projects.settings.switchProject(projectData.name);

                                    sendRequest({
                                        url: "projects",
                                        type: "POST",
                                        handleAuthFail: false,
                                        responses: {
                                            200: function(data) {
                                                dialog.dialog( "close" );
                                            },
                                            400: {
                                                'project_exists': function(error) {
                                                    console.log(RED._("projects.clone-project.already-exists2"));
                                                },
                                                'git_error': function(error) {
                                                    console.log(RED._("projects.clone-project.git-error"),error);
                                                },
                                                'git_connection_failed': function(error) {
                                                    projectRepoInput.addClass("input-error");
                                                    $("#red-ui-projects-dialog-screen-create-project-repo-label small").text(RED._("projects.clone-project.connection-failed"));
                                                },
                                                'git_not_a_repository': function(error) {
                                                    projectRepoInput.addClass("input-error");
                                                    $("#red-ui-projects-dialog-screen-create-project-repo-label small").text(RED._("projects.clone-project.not-git-repo"));
                                                },
                                                'git_repository_not_found': function(error) {
                                                    projectRepoInput.addClass("input-error");
                                                    $("#red-ui-projects-dialog-screen-create-project-repo-label small").text(RED._("projects.clone-project.repo-not-found"));
                                                },
                                                'git_auth_failed': function(error) {
                                                    $(".red-ui-projects-dialog-screen-create-row-auth-error").show();

                                                    projectRepoUserInput.addClass("input-error");
                                                    projectRepoPasswordInput.addClass("input-error");
                                                    // getRepoAuthDetails(req);
                                                    projectRepoSSHKeySelect.addClass("input-error");
                                                    projectRepoPassphrase.addClass("input-error");
                                                },
                                                'missing_flow_file': function(error) {
                                                    // This is handled via a runtime notification.
                                                    dialog.dialog("close");
                                                },
                                                'missing_package_file': function(error) {
                                                    // This is handled via a runtime notification.
                                                    dialog.dialog("close");
                                                },
                                                'project_empty': function(error) {
                                                    // This is handled via a runtime notification.
                                                    dialog.dialog("close");
                                                },
                                                'credentials_load_failed': function(error) {
                                                    // This is handled via a runtime notification.
                                                    dialog.dialog("close");
                                                },
                                                '*': function(error) {
                                                    reportUnexpectedError(error);
                                                    $( dialog ).dialog( "close" );
                                                }
                                            }
                                        }
                                    },projectData).then(function() {
                                        RED.menu.setDisabled('menu-item-projects-open',false);
                                        RED.menu.setDisabled('menu-item-projects-settings',false);
                                        RED.events.emit("project:change", {name:name});
                                    }).always(function() {
                                        setTimeout(function() {
                                            RED.deploy.setDeployInflight(false);
                                        },500);
                                    })

                                }
                            }
                        ]
                    }
                }
            })(),
            'default-files': (function() {
                var projectFlowFileInput;
                var projectCredentialFileInput;
                return {
                    content: function(options) {
                        var container = $('<div class="red-ui-projects-dialog-screen-start"></div>');
                        migrateProjectHeader.appendTo(container);
                        var body = $('<div class="red-ui-projects-dialog-screen-start-body"></div>').appendTo(container);

                        $('<p>').text(RED._("projects.default-files.create")).appendTo(body);
                        $('<p>').text(RED._("projects.default-files.desc0")).appendTo(body);
                        $('<p>').text(RED._("projects.default-files.desc1")).appendTo(body);
                        if (!options.existingProject && RED.settings.files) {
                            $('<p>').text(RED._("projects.default-files.desc2")).appendTo(body);
                        }

                        var validateForm = function() {
                            var valid = true;
                            var flowFile = projectFlowFileInput.val();
                            if (flowFile === "" || !/\.json$/.test(flowFile)) {
                                valid = false;
                                if (!projectFlowFileInput.hasClass("input-error")) {
                                    projectFlowFileInput.addClass("input-error");
                                    projectFlowFileInput.next().empty().append('<i style="margin-top: 8px;" class="fa fa-exclamation-triangle"></i>');
                                }
                                projectCredentialFileInput.text("");
                                if (!projectCredentialFileInput.hasClass("input-error")) {
                                    projectCredentialFileInput.addClass("input-error");
                                    projectCredentialFileInput.next().empty().append('<i style="margin-top: 8px;" class="fa fa-exclamation-triangle"></i>');
                                }
                            } else {
                                if (projectFlowFileInput.hasClass("input-error")) {
                                    projectFlowFileInput.removeClass("input-error");
                                    projectFlowFileInput.next().empty();
                                }
                                if (projectCredentialFileInput.hasClass("input-error")) {
                                    projectCredentialFileInput.removeClass("input-error");
                                    projectCredentialFileInput.next().empty();
                                }
                                projectCredentialFileInput.text(flowFile.substring(0,flowFile.length-5)+"_cred.json");
                            }
                            $("#red-ui-projects-dialog-create-default-files").prop('disabled',!valid).toggleClass('disabled ui-button-disabled ui-state-disabled',!valid);
                        }
                        var row = $('<div class="form-row"></div>').appendTo(body);
                        $('<label for="red-ui-projects-dialog-screen-create-project-file">'+RED._("projects.default-files.flow-file")+'</label>').appendTo(row);
                        var subrow = $('<div style="position:relative;"></div>').appendTo(row);
                        var defaultFlowFile = (createProjectOptions.files &&createProjectOptions.files.flow) || (RED.settings.files && RED.settings.files.flow)||"flow.json";
                        projectFlowFileInput = $('<input id="red-ui-projects-dialog-screen-create-project-file" type="text">').val(defaultFlowFile)
                            .on("change keyup paste",validateForm)
                            .appendTo(subrow);
                        $('<div class="red-ui-projects-dialog-screen-input-status"></div>').appendTo(subrow);
                        $('<label class="red-ui-projects-edit-form-sublabel"><small>*.json</small></label>').appendTo(row);

                        var defaultCredentialsFile = (createProjectOptions.files &&createProjectOptions.files.credentials) || (RED.settings.files && RED.settings.files.credentials)||"flow_cred.json";
                        row = $('<div class="form-row"></div>').appendTo(body);
                        $('<label for="red-ui-projects-dialog-screen-create-project-credfile">'+RED._("projects.default-files.credentials-file")+'</label>').appendTo(row);
                        subrow = $('<div style="position:relative;"></div>').appendTo(row);
                        projectCredentialFileInput = $('<div style="width: 100%" class="uneditable-input" id="red-ui-projects-dialog-screen-create-project-credentials">').text(defaultCredentialsFile)
                            .appendTo(subrow);
                        $('<div class="red-ui-projects-dialog-screen-input-status"></div>').appendTo(subrow);

                        setTimeout(function() {
                            projectFlowFileInput.trigger("focus");
                            validateForm();
                        },50);

                        return container;
                    },
                    buttons: function(options) {
                        return [
                            {
                                // id: "red-ui-clipboard-dialog-cancel",
                                text: RED._(options.existingProject ? "common.label.cancel": "common.label.back"),
                                click: function() {
                                    if (options.existingProject) {
                                        $(this).dialog('close');
                                    } else {
                                        show('project-details',options);
                                    }
                                }
                            },
                            {
                                id: "red-ui-projects-dialog-create-default-files",
                                text: RED._("common.label.next"),
                                class: "primary",
                                click: function() {
                                    createProjectOptions.files = {
                                        flow: projectFlowFileInput.val(),
                                        credentials: projectCredentialFileInput.text()
                                    }
                                    if (!options.existingProject) {
                                        createProjectOptions.migrateFiles = true;
                                    }
                                    show('encryption-config',options);
                                }
                            }
                        ]
                    }
                }
            })(),
            'encryption-config': (function() {
                var emptyProjectCredentialInput;
                return {
                    content: function(options) {

                        var container = $('<div class="red-ui-projects-dialog-screen-start"></div>');
                        migrateProjectHeader.appendTo(container);
                        var body = $('<div class="red-ui-projects-dialog-screen-start-body"></div>').appendTo(container);

                        $('<p>').text(RED._("projects.encryption-config.setup")).appendTo(body);
                        if (options.existingProject) {
                            $('<p>').text(RED._("projects.encryption-config.desc0")).appendTo(body);
                            $('<p>').text(RED._("projects.encryption-config.desc1")).appendTo(body);
                        } else {
                            if (RED.settings.flowEncryptionType === 'disabled') {
                                $('<p>').text(RED._("projects.encryption-config.desc2")).appendTo(body);
                                $('<p>').text(RED._("projects.encryption-config.desc3")).appendTo(body);
                                $('<p>').text(RED._("projects.encryption-config.desc4")).appendTo(body);
                            } else {
                                if (RED.settings.flowEncryptionType === 'user') {
                                    $('<p>').text(RED._("projects.encryption-config.desc5")).appendTo(body);
                                } else if (RED.settings.flowEncryptionType === 'system') {
                                    $('<p>').text(RED._("projects.encryption-config.desc6")).appendTo(body);
                                }
                                $('<p>').text(RED._("projects.encryption-config.desc7")).appendTo(body);
                            }
                        }

                        // var row = $('<div class="form-row"></div>').appendTo(body);
                        // $('<label for="">Username</label>').appendTo(row);
                        // var gitUsernameInput = $('<input type="text">').val(currentGitSettings.user.name||"").appendTo(row);
                        // // $('<div style="position:relative;"></div>').text("This does not need to be your real name").appendTo(row);
                        //
                        // row = $('<div class="form-row"></div>').appendTo(body);
                        // $('<label for="">Email</label>').appendTo(row);
                        // var gitEmailInput = $('<input type="text">').val(currentGitSettings.user.email||"").appendTo(row);
                        // // $('<div style="position:relative;"></div>').text("Something something email").appendTo(row);

                        var validateForm = function() {
                            var valid = true;
                            var encryptionState = $("input[name=projects-encryption-type]:checked").val();
                            if (encryptionState === 'enabled') {
                                var encryptionKeyType = $("input[name=projects-encryption-key]:checked").val();
                                if (encryptionKeyType === 'custom') {
                                    valid = valid && emptyProjectCredentialInput.val()!=='';
                                }
                            }
                            $("#red-ui-projects-dialog-create-encryption").prop('disabled',!valid).toggleClass('disabled ui-button-disabled ui-state-disabled',!valid);
                        }


                        var row = $('<div class="form-row red-ui-projects-dialog-screen-create-row red-ui-projects-dialog-screen-create-row-empty"></div>').appendTo(body);
                        $('<label>'+RED._("projects.encryption-config.credentials")+'</label>').appendTo(row);

                        var credentialsBox = $('<div class="red-ui-projects-dialog-credentials-box">').appendTo(row);
                        var credentialsRightBox = $('<div class="red-ui-projects-dialog-credentials-box-right">').appendTo(credentialsBox);
                        var credentialsLeftBox = $('<div class="red-ui-projects-dialog-credentials-box-left">').appendTo(credentialsBox);

                        var credentialsEnabledBox = $('<div class="form-row red-ui-projects-dialog-credentials-box-enabled"></div>').appendTo(credentialsLeftBox);
                        $('<label class="red-ui-projects-edit-form-inline-label"><input type="radio" name="projects-encryption-type" value="enabled"> <i class="fa fa-lock"></i> <span>'+RED._("projects.encryption-config.enable")+'</span></label>').appendTo(credentialsEnabledBox);
                        var credentialsDisabledBox = $('<div class="form-row red-ui-projects-dialog-credentials-box-disabled"></div>').appendTo(credentialsLeftBox);
                        $('<label class="red-ui-projects-edit-form-inline-label"><input type="radio" name="projects-encryption-type" value="disabled"> <i class="fa fa-unlock"></i> <span>'+RED._("projects.encryption-config.disable")+'</span></label>').appendTo(credentialsDisabledBox);

                        credentialsLeftBox.find("input[name=projects-encryption-type]").on("click", function(e) {
                            var val = $(this).val();
                            var toEnable;
                            var toDisable;
                            if (val === 'enabled') {
                                toEnable = credentialsEnabledBox;
                                toDisable = credentialsDisabledBox;
                                $(".projects-encryption-enabled-row").show();
                                $(".projects-encryption-disabled-row").hide();
                                if ($("input[name=projects-encryption-key]:checked").val() === 'custom') {
                                    emptyProjectCredentialInput.trigger("focus");
                                }

                            } else {
                                toDisable = credentialsEnabledBox;
                                toEnable = credentialsDisabledBox;
                                $(".projects-encryption-enabled-row").hide();
                                $(".projects-encryption-disabled-row").show();
                            }

                            toEnable.removeClass("disabled");
                            toDisable.addClass("disabled");
                            validateForm();
                        })

                        row = $('<div class="form-row projects-encryption-enabled-row"></div>').appendTo(credentialsRightBox);
                        $('<label class="red-ui-projects-edit-form-inline-label '+((RED.settings.flowEncryptionType !== 'user')?'disabled':'')+'" style="margin-left: 5px"><input '+((RED.settings.flowEncryptionType !== 'user')?RED._("projects.encryption-config.disabled"):'')+' type="radio" style="vertical-align: middle; margin-top:0; margin-right: 10px;" value="default" name="projects-encryption-key"> <span style="vertical-align: middle;">'+RED._("projects.encryption-config.copy")+'</span></label>').appendTo(row);
                        row = $('<div class="form-row projects-encryption-enabled-row"></div>').appendTo(credentialsRightBox);
                        $('<label class="red-ui-projects-edit-form-inline-label" style="margin-left: 5px"><input type="radio" style="vertical-align: middle; margin-top:0; margin-right: 10px;" value="custom" name="projects-encryption-key"> <span style="vertical-align: middle;">'+RED._("projects.encryption-config.use-custom")+'</span></label>').appendTo(row);
                        row = $('<div class="projects-encryption-enabled-row"></div>').appendTo(credentialsRightBox);
                        emptyProjectCredentialInput = $('<input disabled type="password" style="margin-left: 25px; width: calc(100% - 30px);"></input>').appendTo(row);
                        emptyProjectCredentialInput.typedInput({type:"cred"});
                        emptyProjectCredentialInput.on("change keyup paste", validateForm);

                        row = $('<div class="form-row projects-encryption-disabled-row"></div>').hide().appendTo(credentialsRightBox);
                        $('<div class="" style="padding: 5px 20px;"><i class="fa fa-warning"></i> '+RED._("projects.encryption-config.desc8")+'</div>').appendTo(row);

                        credentialsRightBox.find("input[name=projects-encryption-key]").on("click", function() {
                            var val = $(this).val();
                            emptyProjectCredentialInput.attr("disabled",val === 'default');
                            if (val === "custom") {
                                emptyProjectCredentialInput.trigger("focus");
                            }
                            validateForm();
                        });

                        setTimeout(function() {
                            credentialsLeftBox.find("input[name=projects-encryption-type][value=enabled]").trigger("click");
                            if (RED.settings.flowEncryptionType !== 'user') {
                                credentialsRightBox.find("input[name=projects-encryption-key][value=custom]").trigger("click");
                            } else {
                                credentialsRightBox.find("input[name=projects-encryption-key][value=default]").trigger("click");
                            }
                            validateForm();
                        },100);

                        return container;
                    },
                    buttons: function(options) {
                            return [
                            {
                                // id: "red-ui-clipboard-dialog-cancel",
                                text: RED._("common.label.back"),
                                click: function() {
                                    show('default-files',options);
                                }
                            },
                            {
                                id: "red-ui-projects-dialog-create-encryption",
                                text: RED._(options.existingProject?"projects.encryption-config.create-project-files":"projects.encryption-config.create-project"),
                                class: "primary disabled",
                                disabled: true,
                                click: function() {
                                    var encryptionState = $("input[name=projects-encryption-type]:checked").val();
                                    if (encryptionState === 'enabled') {
                                        var encryptionKeyType = $("input[name=projects-encryption-key]:checked").val();
                                        if (encryptionKeyType === 'custom') {
                                            createProjectOptions.credentialSecret = emptyProjectCredentialInput.val();
                                        } else {
                                            // If 'use existing', leave createProjectOptions.credentialSecret blank
                                            // - that will trigger it to use the existing key
                                            // TODO: this option should be disabled if encryption is disabled
                                        }
                                    } else {
                                        // Disabled encryption by explicitly setting credSec to false
                                        createProjectOptions.credentialSecret = false;
                                    }
                                    RED.deploy.setDeployInflight(true);
                                    RED.projects.settings.switchProject(createProjectOptions.name);

                                    var method = "POST";
                                    var url = "projects";

                                    if (options.existingProject) {
                                        createProjectOptions.initialise = true;
                                        method = "PUT";
                                        url = "projects/"+activeProject.name;
                                    }
                                    var self = this;
                                    sendRequest({
                                        url: url,
                                        type: method,
                                        requireCleanWorkspace: true,
                                        handleAuthFail: false,
                                        responses: {
                                            200: function(data) {
                                                createProjectOptions = {};
                                                if (options.existingProject) {
                                                    $( self ).dialog( "close" );
                                                } else {
                                                    show('create-success');
                                                    RED.menu.setDisabled('menu-item-projects-open',false);
                                                    RED.menu.setDisabled('menu-item-projects-settings',false);
                                                }
                                            },
                                            400: {
                                                'project_exists': function(error) {
                                                    console.log(RED._("projects.encryption-config.already-exists"));
                                                },
                                                'git_error': function(error) {
                                                    console.log(RED._("projects.encryption-config.git-error"),error);
                                                },
                                                'git_connection_failed': function(error) {
                                                    projectRepoInput.addClass("input-error");
                                                },
                                                'git_auth_failed': function(error) {
                                                    projectRepoUserInput.addClass("input-error");
                                                    projectRepoPasswordInput.addClass("input-error");
                                                    // getRepoAuthDetails(req);
                                                    console.log(RED._("projects.encryption-config.git-auth-error"),error);
                                                },
                                                '*': function(error) {
                                                    reportUnexpectedError(error);
                                                    $( dialog ).dialog( "close" );
                                                }
                                            }
                                        }
                                    },createProjectOptions).always(function() {
                                        setTimeout(function() {
                                            RED.deploy.setDeployInflight(false);
                                        },500);
                                    })
                                }
                            }
                        ];
                    }
                }
            })(),
            'create-success': {
                content: function(options) {

                    var container = $('<div class="red-ui-projects-dialog-screen-start"></div>');
                    migrateProjectHeader.appendTo(container);
                    var body = $('<div class="red-ui-projects-dialog-screen-start-body"></div>').appendTo(container);

                    $('<p>').text(RED._("projects.create-success.success")).appendTo(body);
                    $('<p>').text(RED._("projects.create-success.desc0")).appendTo(body);
                    $('<p>').text(RED._("projects.create-success.desc1")).appendTo(body);
                    $('<p>').text(RED._("projects.create-success.desc2")).appendTo(body);

                    return container;
                },
                buttons: [
                    {
                        text: RED._("common.label.done"),
                        click: function() {
                            $( this ).dialog( "close" );
                        }
                    }
                ]
            },
            'create': (function() {
                var projectNameInput;
                var projectSummaryInput;
                var projectFlowFileInput;
                var projectSecretInput;
                var projectSecretSelect;
                var copyProject;
                var projectRepoInput;
                var projectCloneSecret;
                var emptyProjectCredentialInput;
                var projectRepoUserInput;
                var projectRepoPasswordInput;
                var projectNameSublabel;
                var projectRepoSSHKeySelect;
                var projectRepoPassphrase;
                var projectRepoRemoteName
                var projectRepoBranch;
                var selectedProject;

                return {
                    title: RED._("projects.create.projects"),
                    content: function(options) {
                        var projectList = null;
                        selectedProject = null;
                        var pendingFormValidation = false;
                        $.getJSON("projects", function(data) {
                            projectList = {};
                            data.projects.forEach(function(p) {
                                projectList[p] = true;
                                if (pendingFormValidation) {
                                    pendingFormValidation = false;
                                    validateForm();
                                }
                            })
                        });

                        var container = $('<div class="red-ui-projects-dialog-screen-create"></div>');
                        var row;

                        var validateForm = function() {
                            var projectName = projectNameInput.val();
                            var valid = true;
                            if (projectNameInputChanged) {
                                if (projectList === null) {
                                    pendingFormValidation = true;
                                    return;
                                }
                                projectNameStatus.empty();
                                if (!/^[a-zA-Z0-9\-_]+$/.test(projectName) || projectList[projectName]) {
                                    projectNameInput.addClass("input-error");
                                    $('<i style="margin-top: 8px;" class="fa fa-exclamation-triangle"></i>').appendTo(projectNameStatus);
                                    projectNameValid = false;
                                    valid = false;
                                    if (projectList[projectName]) {
                                        projectNameSublabel.text(RED._("projects.create.already-exists"));
                                    } else {
                                        projectNameSublabel.text(RED._("projects.create.must-contain"));
                                    }
                                } else {
                                    projectNameInput.removeClass("input-error");
                                    $('<i style="margin-top: 8px;" class="fa fa-check"></i>').appendTo(projectNameStatus);
                                    projectNameSublabel.text(RED._("projects.create.must-contain"));
                                    projectNameValid = true;
                                }
                                projectNameLastChecked = projectName;
                            }
                            valid = projectNameValid;

                            var projectType = $(".red-ui-projects-dialog-screen-create-type.selected").data('type');
                            if (projectType === 'copy') {
                                if (!copyProject) {
                                    valid = false;
                                }
                            } else if (projectType === 'clone') {
                                var repo = projectRepoInput.val();

                                // var validRepo = /^(?:file|git|ssh|https?|[\d\w\.\-_]+@[\w\.]+):(?:\/\/)?[\w\.@:\/~_-]+(?:\/?|\#[\d\w\.\-_]+?)$/.test(repo);
                                var validRepo = repo.length > 0 && !/\s/.test(repo);
                                if (/^https?:\/\/[^/]+@/i.test(repo)) {
                                    $("#red-ui-projects-dialog-screen-create-project-repo-label small").text(RED._("projects.create.no-info-in-url"));
                                    validRepo = false;
                                }
                                if (!validRepo) {
                                    if (projectRepoChanged) {
                                        projectRepoInput.addClass("input-error");
                                    }
                                    valid = false;
                                } else {
                                    projectRepoInput.removeClass("input-error");
                                }
                                if (/^https?:\/\//.test(repo)) {
                                    $(".red-ui-projects-dialog-screen-create-row-creds").show();
                                    $(".red-ui-projects-dialog-screen-create-row-sshkey").hide();
                                } else if (/^(?:ssh|[\S]+?@[\S]+?):(?:\/\/)?/.test(repo)) {
                                    $(".red-ui-projects-dialog-screen-create-row-creds").hide();
                                    $(".red-ui-projects-dialog-screen-create-row-sshkey").show();
                                    // if ( !getSelectedSSHKey(projectRepoSSHKeySelect) ) {
                                    //     valid = false;
                                    // }
                                } else {
                                    $(".red-ui-projects-dialog-screen-create-row-creds").hide();
                                    $(".red-ui-projects-dialog-screen-create-row-sshkey").hide();
                                }


                            } else if (projectType === 'empty') {
                                var flowFile = projectFlowFileInput.val();
                                if (flowFile === "" || !/\.json$/.test(flowFile)) {
                                    valid = false;
                                    if (!projectFlowFileInput.hasClass("input-error")) {
                                        projectFlowFileInput.addClass("input-error");
                                        projectFlowFileInput.next().empty().append('<i style="margin-top: 8px;" class="fa fa-exclamation-triangle"></i>');
                                    }
                                } else {
                                    if (projectFlowFileInput.hasClass("input-error")) {
                                        projectFlowFileInput.removeClass("input-error");
                                        projectFlowFileInput.next().empty();
                                    }
                                }

                                var encryptionState = $("input[name=projects-encryption-type]:checked").val();
                                if (encryptionState === 'enabled') {
                                    var encryptionKeyType = $("input[name=projects-encryption-key]:checked").val();
                                    if (encryptionKeyType === 'custom') {
                                        valid = valid && emptyProjectCredentialInput.val()!==''
                                    }
                                }
                            } else if (projectType === 'open') {
                                valid = !!selectedProject;
                            }

                            $("#red-ui-projects-dialog-create").prop('disabled',!valid).toggleClass('disabled ui-button-disabled ui-state-disabled',!valid);
                        }

                        row = $('<div class="form-row button-group"></div>').appendTo(container);

                        var openProject = $('<button data-type="open" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-folder-open"></i><br/>'+RED._("projects.create.open")+'</button>').appendTo(row);
                        var createAsEmpty = $('<button data-type="empty" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-asterisk"></i><br/>'+RED._("projects.create.create")+'</button>').appendTo(row);
                        // var createAsCopy = $('<button data-type="copy" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i class="fa fa-long-arrow-right fa-2x"></i><i class="fa fa-archive fa-2x"></i><br/>Copy existing</button>').appendTo(row);
                        var createAsClone = $('<button data-type="clone" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-git"></i><br/>'+RED._("projects.create.clone")+'</button>').appendTo(row);
                        // var createAsClone = $('<button data-type="clone" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-git fa-2x"></i><i class="fa fa-arrows-h fa-2x"></i><i class="fa fa-archive fa-2x"></i><br/>Clone Repository</button>').appendTo(row);
                        row.find(".red-ui-projects-dialog-screen-create-type").on("click", function(evt) {
                            evt.preventDefault();
                            container.find(".red-ui-projects-dialog-screen-create-type").removeClass('selected');
                            $(this).addClass('selected');
                            container.find(".red-ui-projects-dialog-screen-create-row").hide();
                            container.find(".red-ui-projects-dialog-screen-create-row-"+$(this).data('type')).show();
                            validateForm();
                            projectNameInput.trigger("focus");
                            switch ($(this).data('type')) {
                                case "open": $("#red-ui-projects-dialog-create").text(RED._("projects.create.open")); break;
                                case "empty": $("#red-ui-projects-dialog-create").text(RED._("projects.create.create")); break;
                                case "clone": $("#red-ui-projects-dialog-create").text(RED._("projects.create.clone")); break;
                            }
                        })

                        row = $('<div class="form-row red-ui-projects-dialog-screen-create-row red-ui-projects-dialog-screen-create-row-open"></div>').hide().appendTo(container);
                        createProjectList({
                            canSelectActive: false,
                            dblclick: function(project) {
                                selectedProject = project;
                                $("#red-ui-projects-dialog-create").trigger("click");
                            },
                            select: function(project) {
                                selectedProject = project;
                                validateForm();
                            },
                            delete: function(project) {
                                if (projectList) {
                                    delete projectList[project.name];
                                }
                                selectedProject = null;

                                validateForm();
                            }
                        }).appendTo(row);

                        row = $('<div class="form-row red-ui-projects-dialog-screen-create-row red-ui-projects-dialog-screen-create-row-empty red-ui-projects-dialog-screen-create-row-clone"></div>').appendTo(container);
                        $('<label for="red-ui-projects-dialog-screen-create-project-name">'+RED._("projects.create.project-name")+'</label>').appendTo(row);

                        var subrow = $('<div style="position:relative;"></div>').appendTo(row);
                        projectNameInput = $('<input id="red-ui-projects-dialog-screen-create-project-name" type="text"></input>').appendTo(subrow);
                        var projectNameStatus = $('<div class="red-ui-projects-dialog-screen-input-status"></div>').appendTo(subrow);

                        var projectNameInputChanged = false;
                        var projectNameLastChecked = "";
                        var projectNameValid;
                        var checkProjectName;
                        var autoInsertedName = "";


                        projectNameInput.on("change keyup paste",function() {
                            projectNameInputChanged = (projectNameInput.val() !== projectNameLastChecked);
                            if (checkProjectName) {
                                clearTimeout(checkProjectName);
                            } else if (projectNameInputChanged) {
                                projectNameStatus.empty();
                                $('<img src="red/images/spin.svg"/>').appendTo(projectNameStatus);
                                if (projectNameInput.val() === '') {
                                    validateForm();
                                    return;
                                }
                            }
                            checkProjectName = setTimeout(function() {
                                validateForm();
                                checkProjectName = null;
                            },300)
                        });
                        projectNameSublabel = $('<label class="red-ui-projects-edit-form-sublabel"><small>'+RED._("projects.create.must-contain")+'</small></label>').appendTo(row).find("small");

                        // Empty Project
                        row = $('<div class="form-row red-ui-projects-dialog-screen-create-row red-ui-projects-dialog-screen-create-row-empty"></div>').appendTo(container);
                        $('<label for="red-ui-projects-dialog-screen-create-project-desc">'+RED._("projects.create.desc")+'</label>').appendTo(row);
                        projectSummaryInput = $('<input id="red-ui-projects-dialog-screen-create-project-desc" type="text">').appendTo(row);
                        $('<label class="red-ui-projects-edit-form-sublabel"><small>'+RED._("projects.create.opt")+'</small></label>').appendTo(row);

                        row = $('<div class="form-row red-ui-projects-dialog-screen-create-row red-ui-projects-dialog-screen-create-row-empty"></div>').appendTo(container);
                        $('<label for="red-ui-projects-dialog-screen-create-project-file">'+RED._("projects.create.flow-file")+'</label>').appendTo(row);
                        subrow = $('<div style="position:relative;"></div>').appendTo(row);
                        projectFlowFileInput = $('<input id="red-ui-projects-dialog-screen-create-project-file" type="text">').val("flow.json")
                            .on("change keyup paste",validateForm)
                            .appendTo(subrow);
                        $('<div class="red-ui-projects-dialog-screen-input-status"></div>').appendTo(subrow);
                        $('<label class="red-ui-projects-edit-form-sublabel"><small>*.json</small></label>').appendTo(row);

                        row = $('<div class="form-row red-ui-projects-dialog-screen-create-row red-ui-projects-dialog-screen-create-row-empty"></div>').appendTo(container);
                        $('<label>'+RED._("projects.create.credentials")+'</label>').appendTo(row);

                        var credentialsBox = $('<div class="red-ui-projects-dialog-credentials-box">').appendTo(row);
                        var credentialsRightBox = $('<div class="red-ui-projects-dialog-credentials-box-right">').appendTo(credentialsBox);
                        var credentialsLeftBox = $('<div class="red-ui-projects-dialog-credentials-box-left">').appendTo(credentialsBox);

                        var credentialsEnabledBox = $('<div class="form-row red-ui-projects-dialog-credentials-box-enabled"></div>').appendTo(credentialsLeftBox);
                        $('<label class="red-ui-projects-edit-form-inline-label"><input type="radio" name="projects-encryption-type" value="enabled"> <i class="fa fa-lock"></i> <span>'+RED._("projects.encryption-config.enable")+'</span></label>').appendTo(credentialsEnabledBox);
                        var credentialsDisabledBox = $('<div class="form-row red-ui-projects-dialog-credentials-box-disabled disabled"></div>').appendTo(credentialsLeftBox);
                        $('<label class="red-ui-projects-edit-form-inline-label"><input type="radio" name="projects-encryption-type" value="disabled"> <i class="fa fa-unlock"></i> <span>'+RED._("projects.encryption-config.disable")+'</span></label>').appendTo(credentialsDisabledBox);

                        credentialsLeftBox.find("input[name=projects-encryption-type]").on("click", function(e) {
                            var val = $(this).val();
                            var toEnable;
                            var toDisable;
                            if (val === 'enabled') {
                                toEnable = credentialsEnabledBox;
                                toDisable = credentialsDisabledBox;
                                $(".projects-encryption-enabled-row").show();
                                $(".projects-encryption-disabled-row").hide();
                                if ($("input[name=projects-encryption-key]:checked").val() === 'custom') {
                                    emptyProjectCredentialInput.trigger("focus");
                                }
                            } else {
                                toDisable = credentialsEnabledBox;
                                toEnable = credentialsDisabledBox;
                                $(".projects-encryption-enabled-row").hide();
                                $(".projects-encryption-disabled-row").show();

                            }
                            toEnable.removeClass("disabled");
                            toDisable.addClass("disabled");
                            validateForm();
                        })

                        row = $('<div class="form-row projects-encryption-enabled-row"></div>').appendTo(credentialsRightBox);
                        $('<label class="red-ui-projects-edit-form-inline-label">'+RED._("projects.create.encryption-key")+'</label>').appendTo(row);
                        // row = $('<div class="projects-encryption-enabled-row"></div>').appendTo(credentialsRightBox);
                        emptyProjectCredentialInput = $('<input type="password"></input>').appendTo(row);
                        emptyProjectCredentialInput.typedInput({type:"cred"});
                        emptyProjectCredentialInput.on("change keyup paste", validateForm);
                        $('<label class="red-ui-projects-edit-form-sublabel"><small>'+RED._("projects.create.desc0")+'</small></label>').appendTo(row);


                        row = $('<div class="form-row projects-encryption-disabled-row"></div>').hide().appendTo(credentialsRightBox);
                        $('<div class="" style="padding: 5px 20px;"><i class="fa fa-warning"></i> '+RED._("projects.create.desc1")+'</div>').appendTo(row);

                        credentialsRightBox.find("input[name=projects-encryption-key]").on("click", function() {
                            var val = $(this).val();
                            emptyProjectCredentialInput.attr("disabled",val === 'default');
                            if (val === "custom") {
                                emptyProjectCredentialInput.trigger("focus");
                            }
                            validateForm();
                        })

                        // Clone Project
                        row = $('<div class="hide form-row red-ui-projects-dialog-screen-create-row red-ui-projects-dialog-screen-create-row-clone"></div>').appendTo(container);
                        $('<label for="red-ui-projects-dialog-screen-create-project-repo">'+RED._("projects.create.git-url")+'</label>').appendTo(row);
                        projectRepoInput = $('<input id="red-ui-projects-dialog-screen-create-project-repo" type="text" placeholder="https://git.example.com/path/my-project.git"></input>').appendTo(row);
                        $('<label id="red-ui-projects-dialog-screen-create-project-repo-label" class="red-ui-projects-edit-form-sublabel"><small>'+RED._("projects.create.protocols")+'</small></label>').appendTo(row);

                        var projectRepoChanged = false;
                        var lastProjectRepo = "";
                        projectRepoInput.on("change keyup paste",function() {
                            projectRepoChanged = true;
                            var repo = $(this).val();
                            if (lastProjectRepo !== repo) {
                                $("#red-ui-projects-dialog-screen-create-project-repo-label small").text(RED._("projects.create.protocols"));
                            }
                            lastProjectRepo = repo;

                            var m = /\/([^/]+?)(?:\.git)?$/.exec(repo);
                            if (m) {
                                var projectName = projectNameInput.val();
                                if (projectName === "" || projectName === autoInsertedName) {
                                    autoInsertedName = m[1];
                                    projectNameInput.val(autoInsertedName);
                                    projectNameInput.trigger("change");
                                }
                            }
                            validateForm();
                        });


                        var cloneAuthRows = $('<div class="hide red-ui-projects-dialog-screen-create-row red-ui-projects-dialog-screen-create-row-clone"></div>').hide().appendTo(container);
                        row = $('<div class="form-row red-ui-projects-dialog-screen-create-row-auth-error"></div>').hide().appendTo(cloneAuthRows);
                        $('<div><i class="fa fa-warning"></i> '+RED._("projects.create.auth-failed")+'</div>').appendTo(row);

                        // Repo credentials - username/password ----------------
                        row = $('<div class="hide form-row red-ui-projects-dialog-screen-create-row-creds"></div>').hide().appendTo(cloneAuthRows);

                        var subrow = $('<div style="width: calc(50% - 10px); display:inline-block;"></div>').appendTo(row);
                        $('<label for="red-ui-projects-dialog-screen-create-project-repo-user">'+RED._("projects.create.username")+'</label>').appendTo(subrow);
                        projectRepoUserInput = $('<input id="red-ui-projects-dialog-screen-create-project-repo-user" type="text"></input>').appendTo(subrow);

                        subrow = $('<div style="width: calc(50% - 10px); margin-left: 20px; display:inline-block;"></div>').appendTo(row);
                        $('<label for="red-ui-projects-dialog-screen-create-project-repo-pass">'+RED._("projects.create.password")+'</label>').appendTo(subrow);
                        projectRepoPasswordInput = $('<input style="width:100%" id="red-ui-projects-dialog-screen-create-project-repo-pass" type="password"></input>').appendTo(subrow);
                        projectRepoPasswordInput.typedInput({type:"cred"});
                        // -----------------------------------------------------

                        // Repo credentials - key/passphrase -------------------
                        row = $('<div class="form-row red-ui-projects-dialog-screen-create-row red-ui-projects-dialog-screen-create-row-sshkey"></div>').hide().appendTo(cloneAuthRows);
                        subrow = $('<div style="width: calc(50% - 10px); display:inline-block;"></div>').appendTo(row);
                        $('<label for="red-ui-projects-dialog-screen-create-project-repo-passphrase">'+RED._("projects.create.ssh-key")+'</label>').appendTo(subrow);
                        projectRepoSSHKeySelect = $("<select>",{style:"width: 100%"}).appendTo(subrow);

                        $.getJSON("settings/user/keys", function(data) {
                            var count = 0;
                            data.keys.forEach(function(key) {
                                projectRepoSSHKeySelect.append($("<option></option>").val(key.name).text(key.name));
                                count++;
                            });
                            if (count === 0) {
                                projectRepoSSHKeySelect.addClass("input-error");
                                projectRepoSSHKeySelect.attr("disabled",true);
                                sshwarningRow.show();
                            } else {
                                projectRepoSSHKeySelect.removeClass("input-error");
                                projectRepoSSHKeySelect.attr("disabled",false);
                                sshwarningRow.hide();
                            }
                        });
                        subrow = $('<div style="width: calc(50% - 10px); margin-left: 20px; display:inline-block;"></div>').appendTo(row);
                        $('<label for="red-ui-projects-dialog-screen-create-project-repo-passphrase">'+RED._("projects.create.passphrase")+'</label>').appendTo(subrow);
                        projectRepoPassphrase = $('<input id="red-ui-projects-dialog-screen-create-project-repo-passphrase" type="password"></input>').appendTo(subrow);
                        projectRepoPassphrase.typedInput({type:"cred"});

                        subrow = $('<div class="form-row red-ui-projects-dialog-screen-create-row red-ui-projects-dialog-screen-create-row-sshkey"></div>').appendTo(cloneAuthRows);
                        var sshwarningRow = $('<div class="red-ui-projects-dialog-screen-create-row-auth-error-no-keys"></div>').hide().appendTo(subrow);
                        $('<div class="form-row"><i class="fa fa-warning"></i> '+RED._("projects.create.desc2")+'</div>').appendTo(sshwarningRow);
                        subrow = $('<div style="text-align: center">').appendTo(sshwarningRow);
                        $('<button class="red-ui-button red-ui-projects-dialog-button">'+RED._("projects.create.add-ssh-key")+'</button>').appendTo(subrow).on("click", function(e) {
                            e.preventDefault();
                            $('#red-ui-projects-dialog-cancel').trigger("click");
                            RED.userSettings.show('gitconfig');
                            setTimeout(function() {
                                $("#user-settings-gitconfig-add-key").trigger("click");
                            },500);
                        });
                        // -----------------------------------------------------


                        // Secret - clone
                        row = $('<div class="hide form-row red-ui-projects-dialog-screen-create-row red-ui-projects-dialog-screen-create-row-clone"></div>').appendTo(container);
                        $('<label>'+RED._("projects.create.credentials-encryption-key")+'</label>').appendTo(row);
                        projectSecretInput = $('<input style="width:100%" type="password"></input>').appendTo(row);
                        projectSecretInput.typedInput({type:"cred"});

                        switch(options.screen||"empty") {
                            case "empty": createAsEmpty.trigger("click"); break;
                            case "open":  openProject.trigger("click"); break;
                            case "clone": createAsClone.trigger("click"); break;
                        }

                        setTimeout(function() {
                            if ((options.screen||"empty") !== "open") {
                                projectNameInput.trigger("focus");
                            } else {
                                $("#red-ui-projects-dialog-project-list-search").trigger("focus");
                            }
                        },50);
                        return container;
                    },
                    buttons: function(options) {
                        var initialLabel;
                        switch (options.screen||"empty") {
                            case "open": initialLabel = RED._("projects.create.open"); break;
                            case "empty": initialLabel = RED._("projects.create.create"); break;
                            case "clone": initialLabel = RED._("projects.create.clone"); break;
                        }
                        return [
                            {
                                id: "red-ui-projects-dialog-cancel",
                                text: RED._("common.label.cancel"),
                                click: function() {
                                    $( this ).dialog( "close" );
                                }
                            },
                            {
                                id: "red-ui-projects-dialog-create",
                                text: initialLabel,
                                class: "primary disabled",
                                disabled: true,
                                click: function() {
                                    var projectType = $(".red-ui-projects-dialog-screen-create-type.selected").data('type');
                                    var projectData = {
                                        name: projectNameInput.val(),
                                    }
                                    if (projectType === 'empty') {
                                        projectData.summary = projectSummaryInput.val();
                                        projectData.files = {
                                            flow: projectFlowFileInput.val()
                                        };
                                        var encryptionState = $("input[name=projects-encryption-type]:checked").val();
                                        if (encryptionState === 'enabled') {
                                            projectData.credentialSecret = emptyProjectCredentialInput.val();
                                        } else {
                                            // Disabled encryption by explicitly setting credSec to false
                                            projectData.credentialSecret = false;
                                        }


                                    } else if (projectType === 'copy') {
                                        projectData.copy = copyProject.name;
                                    } else if (projectType === 'clone') {
                                        projectData.credentialSecret = projectSecretInput.val();
                                        var repoUrl = projectRepoInput.val();
                                        var metaData = {};
                                        if (/^(?:ssh|[\d\w\.\-_]+@[\w\.]+):(?:\/\/)?/.test(repoUrl)) {
                                            var selected = projectRepoSSHKeySelect.val();//false;//getSelectedSSHKey(projectRepoSSHKeySelect);
                                            if ( selected ) {
                                                projectData.git = {
                                                    remotes: {
                                                        'origin': {
                                                            url: repoUrl,
                                                            keyFile: selected,
                                                            passphrase: projectRepoPassphrase.val()
                                                        }
                                                    }
                                                };
                                            }
                                            else {
                                                console.log(RED._("projects.create.cant-get-ssh-key-path"));
                                                return;
                                            }
                                        }
                                        else {
                                            projectData.git = {
                                                remotes: {
                                                    'origin': {
                                                        url: repoUrl,
                                                        username: projectRepoUserInput.val(),
                                                        password: projectRepoPasswordInput.val()
                                                    }
                                                }
                                            };
                                        }
                                    } else if (projectType === 'open') {
                                        return switchProject(selectedProject.name,function(err,data) {
                                            if (err) {
                                                if (err.code !== 'credentials_load_failed') {
                                                    console.log(RED._("projects.create.unexpected_error"),err)
                                                }
                                            }
                                        })
                                    }

                                    $(".red-ui-projects-dialog-screen-create-row-auth-error").hide();
                                    $("#red-ui-projects-dialog-screen-create-project-repo-label small").text(RED._("projects.create.protocols"));

                                    projectRepoUserInput.removeClass("input-error");
                                    projectRepoPasswordInput.removeClass("input-error");
                                    projectRepoSSHKeySelect.removeClass("input-error");
                                    projectRepoPassphrase.removeClass("input-error");

                                    RED.deploy.setDeployInflight(true);
                                    RED.projects.settings.switchProject(projectData.name);

                                    sendRequest({
                                        url: "projects",
                                        type: "POST",
                                        handleAuthFail: false,
                                        responses: {
                                            200: function(data) {
                                                dialog.dialog( "close" );
                                            },
                                            400: {
                                                'project_exists': function(error) {
                                                    console.log(RED._("projects.create.already-exists-2"));
                                                },
                                                'git_error': function(error) {
                                                    console.log(RED._("projects.create.git-error"),error);
                                                },
                                                'git_connection_failed': function(error) {
                                                    projectRepoInput.addClass("input-error");
                                                    $("#red-ui-projects-dialog-screen-create-project-repo-label small").text(RED._("projects.create.con-failed"));
                                                },
                                                'git_not_a_repository': function(error) {
                                                    projectRepoInput.addClass("input-error");
                                                    $("#red-ui-projects-dialog-screen-create-project-repo-label small").text(RED._("projects.create.not-git"));
                                                },
                                                'git_repository_not_found': function(error) {
                                                    projectRepoInput.addClass("input-error");
                                                    $("#red-ui-projects-dialog-screen-create-project-repo-label small").text(RED._("projects.create.no-resource"));
                                                },
                                                'git_auth_failed': function(error) {
                                                    $(".red-ui-projects-dialog-screen-create-row-auth-error").show();

                                                    projectRepoUserInput.addClass("input-error");
                                                    projectRepoPasswordInput.addClass("input-error");
                                                    // getRepoAuthDetails(req);
                                                    projectRepoSSHKeySelect.addClass("input-error");
                                                    projectRepoPassphrase.addClass("input-error");
                                                },
                                                'missing_flow_file': function(error) {
                                                    // This is handled via a runtime notification.
                                                    dialog.dialog("close");
                                                },
                                                'missing_package_file': function(error) {
                                                    // This is handled via a runtime notification.
                                                    dialog.dialog("close");
                                                },
                                                'project_empty': function(error) {
                                                    // This is handled via a runtime notification.
                                                    dialog.dialog("close");
                                                },
                                                'credentials_load_failed': function(error) {
                                                    // This is handled via a runtime notification.
                                                    dialog.dialog("close");
                                                },
                                                '*': function(error) {
                                                    reportUnexpectedError(error);
                                                    $( dialog ).dialog( "close" );
                                                }
                                            }
                                        }
                                    },projectData).then(function() {
                                        RED.events.emit("project:change", {name:name});
                                    }).always(function() {
                                        setTimeout(function() {
                                            RED.deploy.setDeployInflight(false);
                                        },500);
                                    })
                                }
                            }
                        ]
                    }
                }
            })()
        }
    }

    function switchProject(name,done) {
        RED.deploy.setDeployInflight(true);
        RED.projects.settings.switchProject(name);
        sendRequest({
            url: "projects/"+name,
            type: "PUT",
            responses: {
                200: function(data) {
                    done(null,data);
                },
                400: {
                    'credentials_load_failed': function(data) {
                        dialog.dialog( "close" );
                        RED.events.emit("project:change", {name:name});
                        done(null,data);
                    },
                    '*': done
                },
            }
        },{active:true}).then(function() {
            dialog.dialog( "close" );
            RED.events.emit("project:change", {name:name});
        }).always(function() {
            setTimeout(function() {
                RED.deploy.setDeployInflight(false);
            },500);
        })
    }

    function deleteProject(row,name,done) {
        var cover = $('<div class="red-ui-projects-dialog-project-list-entry-delete-confirm"></div>').on("click", function(evt) { evt.stopPropagation(); }).appendTo(row);
        $('<span>').text(RED._("projects.delete.confirm")).appendTo(cover);
        $('<button class="red-ui-button red-ui-projects-dialog-button">'+RED._("common.label.cancel")+'</button>')
            .appendTo(cover)
            .on("click", function(e) {
                e.stopPropagation();
                cover.remove();
                done(true);
            });
        $('<button class="red-ui-button red-ui-projects-dialog-button primary">'+RED._("common.label.delete")+'</button>')
            .appendTo(cover)
            .on("click", function(e) {
                e.stopPropagation();
                cover.remove();
                sendRequest({
                    url: "projects/"+name,
                    type: "DELETE",
                    responses: {
                        200: function(data) {
                            done(false);
                        },
                        400: {
                            'unexpected_error': function(error) {
                                cover.remove();
                                done(true);
                            }
                        }
                    }
                });
            });

        setTimeout(function() {
            cover.css("left",0);
        },50);
        //
    }

    function show(s,options) {
        if (!dialog) {
            RED.projects.init();
        }
        var screen = screens[s];
        var container = screen.content(options||{});

        dialogBody.empty();
        var buttons = screen.buttons;
        if (typeof buttons === 'function') {
            buttons = buttons(options||{});
        }



        dialog.dialog('option','buttons',buttons);
        dialogBody.append(container);


        var dialogHeight = 590;
        var winHeight = $(window).height();
        if (winHeight < 750) {
            dialogHeight = 590 - (750 - winHeight);
        }
        $(".red-ui-projects-dialog-box").height(dialogHeight);
        $(".red-ui-projects-dialog-project-list-inner-container").height(Math.max(500,dialogHeight) - 180);
        dialog.dialog('option','title',screen.title||"");
        dialog.dialog("open");
    }

    function createProjectList(options) {
        options = options||{};
        var height = options.height || "200px";
        var container = $('<div></div>',{class:"red-ui-projects-dialog-project-list-container" });
        var filterTerm = "";

        var searchDiv = $("<div>",{class:"red-ui-search-container"}).appendTo(container);
        var searchInput = $('<input id="red-ui-projects-dialog-project-list-search" type="text" placeholder="'+RED._("projects.create-project-list.search")+'">').appendTo(searchDiv).searchBox({
            //data-i18n="[placeholder]menu.label.searchInput"
            delay: 200,
            change: function() {
                filterTerm = $(this).val().toLowerCase();
                list.editableList('filter');
                if (selectedListItem && !selectedListItem.is(":visible")) {
                    selectedListItem.children().children().removeClass('selected');
                    selectedListItem = list.children(":visible").first();
                    selectedListItem.children().children().addClass('selected');
                    if (options.select) {
                        options.select(selectedListItem.children().data('data'));
                    }
                } else {
                    selectedListItem = list.children(":visible").first();
                    selectedListItem.children().children().addClass('selected');
                    if (options.select) {
                        options.select(selectedListItem.children().data('data'));
                    }
                }
                ensureSelectedIsVisible();
            }
        });
        var selectedListItem;

        searchInput.on('keydown',function(evt) {
            if (evt.keyCode === 40) {
                evt.preventDefault();
                // Down
                var next = selectedListItem;
                if (selectedListItem) {
                    do {
                        next = next.next();
                    } while(next.length !== 0 && !next.is(":visible"));
                    if (next.length === 0) {
                        return;
                    }
                    selectedListItem.children().children().removeClass('selected');
                } else {
                    next = list.children(":visible").first();
                }
                selectedListItem = next;
                selectedListItem.children().children().addClass('selected');
                if (options.select) {
                    options.select(selectedListItem.children().data('data'));
                }
                ensureSelectedIsVisible();
            } else if (evt.keyCode === 38) {
                evt.preventDefault();
                // Up
                var prev = selectedListItem;
                if (selectedListItem) {
                    do {
                        prev = prev.prev();
                    } while(prev.length !== 0 && !prev.is(":visible"));
                    if (prev.length === 0) {
                        return;
                    }
                    selectedListItem.children().children().removeClass('selected');
                } else {
                    prev = list.children(":visible").first();
                }
                selectedListItem = prev;
                selectedListItem.children().children().addClass('selected');
                if (options.select) {
                    options.select(selectedListItem.children().data('data'));
                }
                ensureSelectedIsVisible();
            } else if (evt.keyCode === 13) {
                evt.preventDefault();
                // Enter
                if (selectedListItem) {
                    if (options.dblclick) {
                        options.dblclick(selectedListItem.children().data('data'));
                    }
                }
            }
        });

        searchInput.i18n();

        var ensureSelectedIsVisible = function() {
            var selectedEntry = list.find(".red-ui-projects-dialog-project-list-entry.selected").parent().parent();
            if (selectedEntry.length === 1) {
                var scrollWindow = listContainer;
                var scrollHeight = scrollWindow.height();
                var scrollOffset = scrollWindow.scrollTop();
                var y = selectedEntry.position().top;
                var h = selectedEntry.height();
                if (y+h > scrollHeight) {
                    scrollWindow.animate({scrollTop: '-='+(scrollHeight-y-h)},50);
                } else if (y<0) {
                    scrollWindow.animate({scrollTop: '+='+y},50);
                }
            }
        }

        var listContainer = $('<div></div>',{class:"red-ui-projects-dialog-project-list-inner-container" }).appendTo(container);

        var list = $('<ol>',{class:"red-ui-projects-dialog-project-list"}).appendTo(listContainer).editableList({
            addButton: false,
            height:"auto",
            scrollOnAdd: false,
            addItem: function(row,index,entry) {
                var header = $('<div></div>',{class:"red-ui-projects-dialog-project-list-entry"}).appendTo(row);
                $('<span class="red-ui-projects-dialog-project-list-entry-icon"><i class="fa fa-archive"></i></span>').appendTo(header);
                $('<span class="red-ui-projects-dialog-project-list-entry-name" style=""></span>').text(entry.name).appendTo(header);
                if (activeProject && activeProject.name === entry.name) {
                    header.addClass("projects-list-entry-current");
                    $('<span class="red-ui-projects-dialog-project-list-entry-current">'+RED._("projects.create-project-list.current")+'</span>').appendTo(header);
                    if (options.canSelectActive === false) {
                        // active project cannot be selected; so skip the rest
                        return
                    }
                }

                header.addClass("selectable");

                var tools = $('<div class="red-ui-projects-dialog-project-list-entry-tools"></div>').appendTo(header);
                $('<button class="red-ui-button red-ui-projects-dialog-button red-ui-button-small" style="float: right;"><i class="fa fa-trash"></i></button>')
                    .appendTo(tools)
                    .on("click", function(e) {
                        e.stopPropagation();
                        e.preventDefault();
                        deleteProject(row,entry.name, function(cancelled) {
                            if (!cancelled) {
                                row.fadeOut(300,function() {
                                    list.editableList('removeItem',entry);
                                    if (options.delete) {
                                        options.delete(entry);
                                    }
                                });
                            }
                        })
                    });


                row.on("click", function(evt) {
                    $('.red-ui-projects-dialog-project-list-entry').removeClass('selected');
                    header.addClass('selected');
                    selectedListItem = row.parent();
                    if (options.select) {
                        options.select(entry);
                    }
                    ensureSelectedIsVisible();
                    searchInput.trigger("focus");
                })
                if (options.dblclick) {
                    row.on("dblclick", function(evt) {
                        evt.preventDefault();
                        options.dblclick(entry);
                    })
                }
            },
            filter: function(data) {
                if (filterTerm === "") { return true; }
                return data.name.toLowerCase().indexOf(filterTerm) !== -1;
            }
        });
        $.getJSON("projects", function(data) {
            data.projects.forEach(function(project) {
                list.editableList('addItem',{name:project});
            });
        })
        return container;
    }



    function requireCleanWorkspace(done) {
        if (RED.nodes.dirty()) {
            var message = RED._("projects.require-clean.confirm");
            var cleanNotification = RED.notify(message,{
                type:"info",
                fixed: true,
                modal: true,
                buttons: [
                    {
                        //id: "node-dialog-delete",
                        //class: 'leftButton',
                        text: RED._("common.label.cancel"),
                        click: function() {
                            cleanNotification.close();
                            done(true);
                        }
                    },{
                        text: RED._("common.label.cont"),
                        click: function() {
                            cleanNotification.close();
                            done(false);
                        }
                    }
                ]
            });

        }
    }

    function sendRequest(options,body) {
        // dialogBody.hide();
        // console.log(options.url,body);
        if (options.requireCleanWorkspace && RED.nodes.dirty()) {
            var thenCallback;
            var alwaysCallback;
            requireCleanWorkspace(function(cancelled) {
                if (cancelled) {
                    if (options.cancel) {
                        options.cancel();
                        if (alwaysCallback) {
                            alwaysCallback();
                        }
                    }
                } else {
                    delete options.requireCleanWorkspace;
                    sendRequest(options,body).then(function() {
                        if (thenCallback) {
                            thenCallback();
                        }
                    }).always(function() {
                        if (alwaysCallback) {
                            alwaysCallback();
                        }

                    })
                }
            })
            // What follows is a very hacky Promise-like api thats good enough
            // for our needs.
            return {
                then: function(done) {
                    thenCallback = done;
                    return { always: function(done) { alwaysCallback = done; }}
                 },
                always: function(done) { alwaysCallback = done; }
            }
        }

        var start = Date.now();
        // TODO: this is specific to the dialog-based requests
        $(".red-ui-component-spinner").show();
        $("#red-ui-projects-dialog").parent().find(".ui-dialog-buttonset").children().css("visibility","hidden")
        if (body) {
            options.data = JSON.stringify(body);
            options.contentType = "application/json; charset=utf-8";
        }
        var resultCallback;
        var resultCallbackArgs;
        return $.ajax(options).done(function(data,textStatus,xhr) {
            if (options.responses && options.responses[200]) {
                resultCallback = options.responses[200];
                resultCallbackArgs = data;
            }
        }).fail(function(xhr,textStatus,err) {
            var responses;

            if (options.responses && options.responses[xhr.status]) {
                responses = options.responses[xhr.status];
                if (typeof responses === 'function') {
                    resultCallback = responses;
                    resultCallbackArgs = {error:responses.statusText};
                    return;
                } else if (options.handleAuthFail !== false && (xhr.responseJSON.code === 'git_auth_failed' || xhr.responseJSON.code === 'git_host_key_verification_failed')) {
                    if (xhr.responseJSON.code === 'git_auth_failed') {
                        var url = activeProject.git.remotes[xhr.responseJSON.remote||options.remote||'origin'].fetch;

                        var message = $('<div>'+
                        '<div class="form-row">'+RED._("projects.send-req.auth-req")+':</div>'+
                        '<div class="form-row"><div style="margin-left: 20px;">'+url+'</div></div>'+
                        '</div>');

                        var isSSH = false;
                        if (/^https?:\/\//.test(url)) {
                            $('<div class="form-row"><label for="projects-user-auth-username">'+RED._("projects.send-req.username")+'</label><input id="projects-user-auth-username" type="text"></input></div>'+
                            '<div class="form-row"><label for="projects-user-auth-password">'+RED._("projects.send-req.password")+'</label><input id="projects-user-auth-password" type="password"></input></div>').appendTo(message);
                            message.find("#projects-user-auth-password").typedInput({type:"cred"})
                        } else if (/^(?:ssh|[\d\w\.\-_]+@[\w\.]+):(?:\/\/)?/.test(url)) {
                            isSSH = true;
                            var row = $('<div class="form-row"></div>').appendTo(message);
                            $('<label for="projects-user-auth-key">SSH Key</label>').appendTo(row);
                            var projectRepoSSHKeySelect = $('<select id="projects-user-auth-key">').width('70%').appendTo(row);
                            $.getJSON("settings/user/keys", function(data) {
                                var count = 0;
                                data.keys.forEach(function(key) {
                                    projectRepoSSHKeySelect.append($("<option></option>").val(key.name).text(key.name));
                                    count++;
                                });
                                if (count === 0) {
                                    //TODO: handle no keys yet setup
                                }
                            });
                            row = $('<div class="form-row"></div>').appendTo(message);
                            $('<label for="projects-user-auth-passphrase">'+RED._("projects.send-req.passphrase")+'</label>').appendTo(row);
                            $('<input id="projects-user-auth-passphrase" type="password"></input>').appendTo(row).typedInput({type:"cred"});
                        }

                        var notification = RED.notify(message,{
                            type:"error",
                            fixed: true,
                            modal: true,
                            buttons: [
                                {
                                    //id: "node-dialog-delete",
                                    //class: 'leftButton',
                                    text: RED._("common.label.cancel"),
                                    click: function() {
                                        notification.close();
                                    }
                                },{
                                    text: '<span><i class="fa fa-refresh"></i> ' +RED._("projects.send-req.retry") +'</span>',
                                    click: function() {
                                        body = body || {};
                                        var authBody = {};
                                        if (isSSH) {
                                            authBody.keyFile = $('#projects-user-auth-key').val();
                                            authBody.passphrase = $('#projects-user-auth-passphrase').val();
                                        } else {
                                            authBody.username = $('#projects-user-auth-username').val();
                                            authBody.password = $('#projects-user-auth-password').val();
                                        }
                                        var done = function(err) {
                                            if (err) {
                                                console.log(RED._("projects.send-req.update-failed"));
                                                console.log(err);
                                            } else {
                                                sendRequest(options,body);
                                                notification.close();
                                            }

                                        }
                                        sendRequest({
                                            url: "projects/"+activeProject.name+"/remotes/"+(xhr.responseJSON.remote||options.remote||'origin'),
                                            type: "PUT",
                                            responses: {
                                                0: function(error) {
                                                    done(error,null);
                                                },
                                                200: function(data) {
                                                    done(null,data);
                                                },
                                                400: {
                                                    'unexpected_error': function(error) {
                                                        done(error,null);
                                                    }
                                                },
                                            }
                                        },{auth:authBody});
                                    }
                                }
                            ]
                        });
                        return;
                    } else if (xhr.responseJSON.code === 'git_host_key_verification_failed') {
                        var message = $('<div>'+
                            '<div class="form-row">'+RED._("projects.send-req.host-key-verify-failed")+'</div>'+
                            '</div>');
                        var notification = RED.notify(message,{
                            type:"error",
                            fixed: true,
                            modal: true,
                            buttons: [
                                {
                                    text: RED._("common.label.close"),
                                    click: function() {
                                        notification.close();
                                    }
                                }
                            ]
                        });
                        return;
                    }
                } else if (responses[xhr.responseJSON.code]) {
                    resultCallback = responses[xhr.responseJSON.code];
                    resultCallbackArgs = xhr.responseJSON;
                    return;
                } else if (responses['*']) {
                    resultCallback = responses['*'];
                    resultCallbackArgs = xhr.responseJSON;
                    return;
                }
            }
            console.log(responses)
            console.log(RED._("projects.send-req.unhandled")+":");
            console.log(xhr);
            console.log(textStatus);
            console.log(err);
        }).always(function() {
            var delta = Date.now() - start;
            delta = Math.max(0,500-delta);
            setTimeout(function() {
                // dialogBody.show();
                $(".red-ui-component-spinner").hide();
                $("#red-ui-projects-dialog").parent().find(".ui-dialog-buttonset").children().css("visibility","")
                if (resultCallback) {
                    resultCallback(resultCallbackArgs)
                }
            },delta);
        });
    }

    function createBranchList(options) {
        var branchFilterTerm = "";
        var branchFilterCreateItem;
        var branches = [];
        var branchNames = new Set();
        var remotes = [];
        var branchPrefix = "";
        var container = $('<div class="red-ui-projects-branch-list">').appendTo(options.container);

        var branchFilter = $('<input type="text">').attr('placeholder',options.placeholder).appendTo(container).searchBox({
            delay: 200,
            change: function() {
                branchFilterTerm = $(this).val();
                // if there is a / then
                //  - check what preceeds it is a known remote

                var valid = false;
                var hasRemote = false;
                var m = /^([^/]+)\/[^/.~*?\[]/.exec(branchFilterTerm);
                if (m && remotes.indexOf(m[1]) > -1) {
                    valid = true;
                    hasRemote = true;
                }

                if (!valid && /(\.\.|\/\.|[?*[~^: \\]|\/\/|\/.$|\/$)/.test(branchFilterTerm)) {
                    if (!branchFilterCreateItem.hasClass("input-error")) {
                        branchFilterCreateItem.addClass("input-error");
                        branchFilterCreateItem.find("i").addClass("fa-warning").removeClass("fa-code-fork");
                    }
                    branchFilterCreateItem.find("span").text(RED._("projects.create-branch-list.invalid")+": "+(hasRemote?"":branchPrefix)+branchFilterTerm);
                } else {
                    if (branchFilterCreateItem.hasClass("input-error")) {
                        branchFilterCreateItem.removeClass("input-error");
                        branchFilterCreateItem.find("i").removeClass("fa-warning").addClass("fa-code-fork");
                    }
                    branchFilterCreateItem.find("span").text(RED._("projects.create-branch-list.create")+":");
                    branchFilterCreateItem.find(".red-ui-sidebar-vc-branch-list-entry-create-name").text((hasRemote?"":branchPrefix)+branchFilterTerm);
                }
                branchList.editableList("filter");
            }
        });
        var branchList = $("<ol>",{style:"height: 130px;"}).appendTo(container);
        branchList.editableList({
            addButton: false,
            scrollOnAdd: false,
            addItem: function(row,index,entry) {
                var container = $('<div class="red-ui-sidebar-vc-branch-list-entry">').appendTo(row);
                if (!entry.hasOwnProperty('commit')) {
                    branchFilterCreateItem = container;
                    $('<i class="fa fa-code-fork"></i>').appendTo(container);
                    $('<span>').text(RED._("projects.create-branch-list.create")+":").appendTo(container);
                    $('<div class="red-ui-sidebar-vc-branch-list-entry-create-name" style="margin-left: 10px;">').text(entry.name).appendTo(container);
                } else {
                    $('<i class="fa fa-code-fork"></i>').appendTo(container);
                    $('<span>').text(entry.name).appendTo(container);
                    if (entry.current) {
                        container.addClass("selected");
                        $('<span class="current"></span>').text(options.currentLabel||RED._("projects.create-branch-list.current")).appendTo(container);
                    }
                }
                container.on("click", function(evt) {
                    evt.preventDefault();
                    if ($(this).hasClass('input-error')) {
                        return;
                    }
                    var body = {};
                    if (!entry.hasOwnProperty('commit')) {
                        body.name = branchFilter.val();
                        body.create = true;

                        if (options.remotes) {
                            var m = /^([^/]+)\/[^/.~*?\[]/.exec(body.name);
                            if (!m || remotes.indexOf(m[1]) === -1) {
                                body.name = remotes[0]+"/"+body.name;
                            }
                        }
                    } else {
                        if ($(this).hasClass('selected')) {
                            body.current = true;
                        }
                        body.name = entry.name;
                    }
                    if (options.onselect) {
                        options.onselect(body);
                    }
                });
            },
            filter: function(data) {
                var isCreateEntry = (!data.hasOwnProperty('commit'));
                var filterTerm = branchFilterTerm;
                if (remotes.length > 0) {
                    var m = /^([^/]+)\/[^/.~*?\[]/.exec(filterTerm);
                    if (filterTerm !== "" && (!m || remotes.indexOf(m[1]) == -1)) {
                        filterTerm = remotes[0]+"/"+filterTerm;
                    }
                }
                return (
                            isCreateEntry &&
                            (
                                filterTerm !== "" && !branchNames.has(filterTerm)
                            )
                     ) ||
                     (
                         !isCreateEntry &&
                         data.name.indexOf(branchFilterTerm) !== -1
                     );
            }
        });
        return {
            refresh: function(url) {
                branchFilter.searchBox("value","");
                branchList.editableList('empty');
                var start = Date.now();
                var spinner = addSpinnerOverlay(container).addClass("red-ui-component-spinner-contain");
                if (options.remotes) {
                    remotes = options.remotes();
                    branchPrefix = remotes[0]+"/";
                } else {
                    branchPrefix = "";
                    remotes = [];
                }
                branchNames = new Set();
                sendRequest({
                    url: url,
                    type: "GET",
                    responses: {
                        0: function(error) {
                            console.log(error);
                        },
                        200: function(result) {
                            branches = result.branches;
                            result.branches.forEach(function(b) {
                                branchList.editableList('addItem',b);
                                branchNames.add(b.name);
                            });
                            branchList.editableList('addItem',{});
                            setTimeout(function() {
                                spinner.remove();
                            },Math.max(300-(Date.now() - start),0));
                        },
                        400: {
                            'git_connection_failed': function(error) {
                                RED.notify(error.message,'error');
                            },
                            'git_not_a_repository': function(error) {
                                RED.notify(error.message,'error');
                            },
                            'git_repository_not_found': function(error) {
                                RED.notify(error.message,'error');
                            },
                            'unexpected_error': function(error) {
                                reportUnexpectedError(error);
                            }
                        }
                    }
                })
            },
            // addItem: function(data) { branchList.editableList('addItem',data) },
            filter: function() { branchList.editableList('filter') },
            focus: function() { branchFilter.trigger("focus") }
        }
    }

    function addSpinnerOverlay(container) {
        var spinner = $('<div class="red-ui-component-spinner"><img src="red/images/spin.svg"/></div>').appendTo(container);
        return spinner;
    }

    function init() {
        dialog = $('<div id="red-ui-projects-dialog" class="hide red-ui-projects-edit-form"><div class="red-ui-projects-dialog-box"><form class="form-horizontal"></form><div class="red-ui-component-spinner hide"><img src="red/images/spin.svg"/></div></div></div>')
            .appendTo("#red-ui-editor")
            .dialog({
                modal: true,
                autoOpen: false,
                width: 600,
                resizable: false,
                open: function(e) {
                    RED.keyboard.disable();
                },
                close: function(e) {
                    RED.keyboard.enable();
                },
                classes: {
                    "ui-dialog": "red-ui-editor-dialog",
                    "ui-dialog-titlebar-close": "hide",
                    "ui-widget-overlay": "red-ui-editor-dialog"
                }
            });
        dialogBody = dialog.find("form");

        RED.actions.add("core:new-project",RED.projects.newProject);
        RED.actions.add("core:open-project",RED.projects.selectProject);
        RED.actions.add("core:show-project-settings",RED.projects.settings.show);
        var projectsAPI = {
            sendRequest:sendRequest,
            createBranchList:createBranchList,
            addSpinnerOverlay:addSpinnerOverlay,
            reportUnexpectedError:reportUnexpectedError
        };
        RED.projects.settings.init(projectsAPI);
        RED.projects.userSettings.init(projectsAPI);
        RED.sidebar.versionControl.init(projectsAPI);
        initScreens();
        // initSidebar();
    }

    function createDefaultFileSet() {
        if (!activeProject) {
            throw new Error(RED._("projects.create-default-file-set.no-active"));
        } else if (!activeProject.empty) {
            throw new Error(RED._("projects.create-default-file-set.no-empty"));
        }
        if (!RED.user.hasPermission("projects.write")) {
            RED.notify(RED._("user.errors.notAuthorized"),"error");
            return;
        }
        createProjectOptions = {};
        show('default-files',{existingProject: true});
    }
    function createDefaultPackageFile() {
        RED.deploy.setDeployInflight(true);
        RED.projects.settings.switchProject(activeProject.name);

        var method = "PUT";
        var url = "projects/"+activeProject.name;
        var createProjectOptions = {
            initialise: true
        };
        sendRequest({
            url: url,
            type: method,
            requireCleanWorkspace: true,
            handleAuthFail: false,
            responses: {
                200: function(data) { },
                400: {
                    'git_error': function(error) {
                        console.log(RED._("projects.create-default-file-set.git-error"),error);
                    },
                    'missing_flow_file': function(error) {
                        // This is a natural next error - but let the runtime event
                        // trigger the dialog rather than double-report it.
                        $( dialog ).dialog( "close" );
                    },
                    '*': function(error) {
                        reportUnexpectedError(error);
                        $( dialog ).dialog( "close" );
                    }
                }
            }
        },createProjectOptions).always(function() {
            setTimeout(function() {
                RED.deploy.setDeployInflight(false);
            },500);
        })
    }

    function refresh(done) {
        $.getJSON("projects",function(data) {
            if (data.active) {
                $.getJSON("projects/"+data.active, function(project) {
                    activeProject = project;
                    RED.events.emit("projects:load",activeProject);
                    RED.sidebar.versionControl.refresh(true);
                    if (done) {
                        done(activeProject);
                    }
                });
            } else {
                if (done) {
                    done(null);
                }
            }
        });
    }


    function showNewProjectScreen() {
        createProjectOptions = {};
        if (!activeProject) {
            show('welcome');
        } else {
            show('create',{screen:'empty'})
        }
    }

    return {
        init: init,
        showStartup: function() {
            console.warn("showStartup")
            if (!RED.user.hasPermission("projects.write")) {
                RED.notify(RED._("user.errors.notAuthorized"),"error");
                return;
            }
            show('welcome');
        },
        newProject: function() {
            if (!RED.user.hasPermission("projects.write")) {
                RED.notify(RED._("user.errors.notAuthorized"),"error");
                return;
            }

            if (RED.nodes.dirty()) {
                return requireCleanWorkspace(function(cancelled) {
                    if (!cancelled) {
                        showNewProjectScreen();
                    }
                })
            } else {
                showNewProjectScreen();
            }
        },
        selectProject: function() {
            if (!RED.user.hasPermission("projects.write")) {
                RED.notify(RED._("user.errors.notAuthorized"),"error");
                return;
            }
            if (RED.nodes.dirty()) {
                return requireCleanWorkspace(function(cancelled) {
                    if (!cancelled) {
                        show('create',{screen:'open'})
                    }
                })
            } else {
                show('create',{screen:'open'})
            }
        },
        showCredentialsPrompt: function() { //TODO: rename this function
            if (!RED.user.hasPermission("projects.write")) {
                RED.notify(RED._("user.errors.notAuthorized"),"error");
                return;
            }
            RED.projects.settings.show('settings');
        },
        showFilesPrompt: function() { //TODO: rename this function
            if (!RED.user.hasPermission("projects.write")) {
                RED.notify(RED._("user.errors.notAuthorized"),"error");
                return;
            }
            RED.projects.settings.show('settings');
            setTimeout(function() {
                $("#project-settings-tab-settings-file-edit").trigger("click");
            },200)
        },
        showProjectDependencies: function() {
            RED.projects.settings.show('deps');
        },
        createDefaultFileSet: createDefaultFileSet,
        createDefaultPackageFile: createDefaultPackageFile,
        // showSidebar: showSidebar,
        refresh: refresh,
        editProject: function() {
            RED.projects.settings.show();
        },
        getActiveProject: function() {
            return activeProject;
        }
    }
})();

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 2.5 [PHP 8 Update] [24.05.2025] | Generation time: 0.0088 ]--