<commit_before>/* Isso – Ich schrei sonst!
 */
define(["app/text/html", "app/dom", "app/utils", "app/api", "app/markup", "app/i18n", "app/lib", "app/fancy"],
    function(templates, $, utils, api, Mark, i18n, lib, fancy) {

    "use strict";

    var msgs = i18n[i18n.lang];

    var Postbox = function(parent) {

        var el = $.htmlify(Mark.up(templates["postbox"]));

        // add a default identicon to not waste CPU cycles
        $(".avatar > svg", el).replace(lib.identicons.blank(4, 48));

        // on text area focus, generate identicon from IP address
        $(".textarea-wrapper > textarea", el).on("focus", function() {
            if ($(".avatar svg", el).classList.contains("blank")) {
                $(".avatar svg", el).replace(
                    lib.identicons.generate(lib.pbkdf2(api.remote_addr, api.salt, 1000, 6), 4, 48));
            }
        });

        // update identicon, when the user provices an email address
        var active;
        $(".input-wrapper > [type=email]", el).on("keyup", function() {
            if (active) {
                clearTimeout(active);
            }
            active = setTimeout(function() {
                lib.pbkdf2($(".input-wrapper > [type=email]", el).value || api.remote_addr, api.salt, 1000, 6)
                .then(function(rv) {
                    $(".avatar svg", el).replace(lib.identicons.generate(rv, 4, 48));
                });
            }, 200);
        }, false);

        $(".input-wrapper > [type=email]", el).on("keydown", function() {
            clearTimeout(active);
        }, false);

        el.onsuccess = function() {};

        el.validate = function() {
            if ($("textarea", this).value.length < 3) {
                $("textarea", this).focus();
                return false;
            }
            return true;
        };

        $("[type=submit]", el).on("click", function() {
            if (! el.validate()) {
                return;
            }

            api.create({
                author: $("[name=author]", el).value || null,
                email: $("[name=email]", el).value || null,
                text: $("textarea", el).value,
                parent: parent || null
            }).then(function(comment) {
                $("[name=author]", el).value = "";
                $("[name=email]", el).value = "";
                $("textarea", el).value = "";
                $("textarea", el).rows = 2;
                $("textarea", el).blur();
                insert(comment, true);

                if (parent !== null) {
                    el.onsuccess();
                    el.remove();
                }
            });
        });

        fancy.autoresize($("textarea", el), 48);

        return el;
    };

    var map  = {id: {}, name: {}};

    var insert = function(comment, scrollIntoView) {

        map.name[comment.id] = comment.author;
        if (comment.parent) {
            comment["replyto"] = map.name[comment.parent];
        }

        var el = $.htmlify(Mark.up(templates["comment"], comment));

        var refresh = function() {
            $(".permalink > date", el).textContent = utils.ago(new Date(parseInt(comment.created, 10) * 1000));
            setTimeout(refresh, 60*1000);
        };  refresh();

        $("div.avatar > svg", el).replace(lib.identicons.generate(comment.hash, 4, 48));

        var entrypoint;
        if (comment.parent === null) {
            entrypoint = $("#isso-root");
        } else {
            var key = comment.parent;
            while (key in map.id) {
                key = map.id[key];
            }
            map.id[comment.id] = comment.parent;
            entrypoint = $("#isso-" + key + " > .text-wrapper > .isso-follow-up");
        }

        entrypoint.append(el);

        if (scrollIntoView) {
            el.scrollIntoView();
        }

        var footer = $("#isso-" + comment.id + " > .text-wrapper > .isso-comment-footer"),
            header = $("#isso-" + comment.id + " > .text-wrapper > .isso-comment-header"),
            text   = $("#isso-" + comment.id + " > .text-wrapper > .text");

        var form = new Postbox(comment.id);
        $("a.reply", footer).toggle("click",
            function(toggler) {
                footer.insertAfter(form);
                form.onsuccess = function() { toggler.next(); };
                $("textarea", form).focus();
                $("a.reply", footer).textContent = msgs["comment-close"];
            },
            function() {
                form.remove();
                $("a.reply", footer).textContent = msgs["comment-reply"];
            }
        );

        if (comment.parent !== null) {
            $("a.parent", header).on("mouseover", function() {
                $("#isso-" + comment.parent).classList.add("parent-highlight");
            });
            $("a.parent", header).on("mouseout", function() {
                $("#isso-" + comment.parent).classList.remove("parent-highlight");
            });
        }

        var votes = function (value) {
            var span = $("span.votes", footer);
            if (span === null) {
                if (value === 0) {
                    span.remove();
                    return;
                } else {
                    footer.prepend($.new("span.votes", value));
                }
            } else {
                if (value === 0) {
                    span.remove();
                } else {
                    span.textContent = value;
                }
            }
        };

        $("a.upvote", footer).on("click", function() {
            api.like(comment.id).then(function(rv) {
                votes(rv.likes - rv.dislikes);
            });
        });

        $("a.downvote", footer).on("click", function() {
            api.dislike(comment.id).then(function(rv) {
                votes(rv.likes - rv.dislikes);
            });
        });

        $("a.edit", footer).toggle("click",
            function(toggler) {
                var edit = $("a.edit", footer);

                edit.textContent = msgs["comment-save"];
                edit.insertAfter($.new("a.cancel", msgs["comment-cancel"])).on("click", function() {
                    text.textContent = "";
                    text.className = "text";
                    text.append(comment.text);
                    toggler.next();
                });

                api.view(comment.id, 1).then(function(rv) {
                    var textarea = $.new("textarea", rv.text);
                    fancy.autoresize(textarea, 48);
                    text.className = "textarea-wrapper";
                    text.textContent = "";
                    text.append(textarea);
                    textarea.focus();
                });
            },
            function(toggler) {
                var textarea = $("textarea", text);
                if (textarea && textarea.value.length < 3) {
                    textarea.focus();
                    toggler.wait();
                    return;
                } else if (textarea) {
                    api.modify(comment.id, {"text": textarea.value}).then(function(rv) {
                        text.innerHTML = rv.text;
                        text.className = "text";
                        comment.text = rv.text;
                    });
                }

                $("a.cancel", footer).remove();
                $("a.edit", footer).textContent = msgs["comment-edit"];
            }
        );

        $("a.delete", footer).on("click", function() {
            if ($("a.delete", footer).textContent === msgs["comment-confirm"]) {
                api.remove(comment.id).then(function(rv) {
                    if (rv) {
                        el.remove();
                    } else {
                        $("span.note", header).textContent = msgs["comment-deleted"];
                        text.innerHTML = "

";
                    }
                });
            } else {
                $("a.delete", footer).textContent = msgs["comment-confirm"];
                setTimeout(function() {
                    $("a.delete", footer).textContent = msgs["comment-delete"];
                }, 1500);
            }
        });

        // remove edit and delete buttons when cookie is gone
        var clear = function(button) {
            if (! utils.cookie(comment.id)) {
                $(button, footer).remove();
            } else {
                setTimeout(function() { clear(button); }, 15*1000);
            }
        };

        clear("a.edit");
        clear("a.delete");

        // show direct reply to own comment when cookie is max aged
        var show = function(el) {
            if (utils.cookie(comment.id)) {
                setTimeout(function() { show(el); }, 15*1000);
            } else {
                footer.append(el);
            }
        };

        if (utils.cookie(comment.id)) {
            show($("a.reply", footer).detach());
        }
    };

    return {
        insert: insert,
        Postbox: Postbox
    };
});<commit_msg>remove button no longer resets after 1.5s, part of #17<commit_after>/* Isso – Ich schrei sonst!
 */
define(["app/text/html", "app/dom", "app/utils", "app/api", "app/markup", "app/i18n", "app/lib", "app/fancy"],
    function(templates, $, utils, api, Mark, i18n, lib, fancy) {

    "use strict";

    var msgs = i18n[i18n.lang];

    var Postbox = function(parent) {

        var el = $.htmlify(Mark.up(templates["postbox"]));

        // add a default identicon to not waste CPU cycles
        $(".avatar > svg", el).replace(lib.identicons.blank(4, 48));

        // on text area focus, generate identicon from IP address
        $(".textarea-wrapper > textarea", el).on("focus", function() {
            if ($(".avatar svg", el).classList.contains("blank")) {
                $(".avatar svg", el).replace(
                    lib.identicons.generate(lib.pbkdf2(api.remote_addr, api.salt, 1000, 6), 4, 48));
            }
        });

        // update identicon, when the user provices an email address
        var active;
        $(".input-wrapper > [type=email]", el).on("keyup", function() {
            if (active) {
                clearTimeout(active);
            }
            active = setTimeout(function() {
                lib.pbkdf2($(".input-wrapper > [type=email]", el).value || api.remote_addr, api.salt, 1000, 6)
                .then(function(rv) {
                    $(".avatar svg", el).replace(lib.identicons.generate(rv, 4, 48));
                });
            }, 200);
        }, false);

        $(".input-wrapper > [type=email]", el).on("keydown", function() {
            clearTimeout(active);
        }, false);

        el.onsuccess = function() {};

        el.validate = function() {
            if ($("textarea", this).value.length < 3) {
                $("textarea", this).focus();
                return false;
            }
            return true;
        };

        $("[type=submit]", el).on("click", function() {
            if (! el.validate()) {
                return;
            }

            api.create({
                author: $("[name=author]", el).value || null,
                email: $("[name=email]", el).value || null,
                text: $("textarea", el).value,
                parent: parent || null
            }).then(function(comment) {
                $("[name=author]", el).value = "";
                $("[name=email]", el).value = "";
                $("textarea", el).value = "";
                $("textarea", el).rows = 2;
                $("textarea", el).blur();
                insert(comment, true);

                if (parent !== null) {
                    el.onsuccess();
                    el.remove();
                }
            });
        });

        fancy.autoresize($("textarea", el), 48);

        return el;
    };

    var map  = {id: {}, name: {}};

    var insert = function(comment, scrollIntoView) {

        map.name[comment.id] = comment.author;
        if (comment.parent) {
            comment["replyto"] = map.name[comment.parent];
        }

        var el = $.htmlify(Mark.up(templates["comment"], comment));

        var refresh = function() {
            $(".permalink > date", el).textContent = utils.ago(new Date(parseInt(comment.created, 10) * 1000));
            setTimeout(refresh, 60*1000);
        };  refresh();

        $("div.avatar > svg", el).replace(lib.identicons.generate(comment.hash, 4, 48));

        var entrypoint;
        if (comment.parent === null) {
            entrypoint = $("#isso-root");
        } else {
            var key = comment.parent;
            while (key in map.id) {
                key = map.id[key];
            }
            map.id[comment.id] = comment.parent;
            entrypoint = $("#isso-" + key + " > .text-wrapper > .isso-follow-up");
        }

        entrypoint.append(el);

        if (scrollIntoView) {
            el.scrollIntoView();
        }

        var footer = $("#isso-" + comment.id + " > .text-wrapper > .isso-comment-footer"),
            header = $("#isso-" + comment.id + " > .text-wrapper > .isso-comment-header"),
            text   = $("#isso-" + comment.id + " > .text-wrapper > .text");

        var form = new Postbox(comment.id);
        $("a.reply", footer).toggle("click",
            function(toggler) {
                footer.insertAfter(form);
                form.onsuccess = function() { toggler.next(); };
                $("textarea", form).focus();
                $("a.reply", footer).textContent = msgs["comment-close"];
            },
            function() {
                form.remove();
                $("a.reply", footer).textContent = msgs["comment-reply"];
            }
        );

        if (comment.parent !== null) {
            $("a.parent", header).on("mouseover", function() {
                $("#isso-" + comment.parent).classList.add("parent-highlight");
            });
            $("a.parent", header).on("mouseout", function() {
                $("#isso-" + comment.parent).classList.remove("parent-highlight");
            });
        }

        var votes = function (value) {
            var span = $("span.votes", footer);
            if (span === null) {
                if (value === 0) {
                    span.remove();
                    return;
                } else {
                    footer.prepend($.new("span.votes", value));
                }
            } else {
                if (value === 0) {
                    span.remove();
                } else {
                    span.textContent = value;
                }
            }
        };

        $("a.upvote", footer).on("click", function() {
            api.like(comment.id).then(function(rv) {
                votes(rv.likes - rv.dislikes);
            });
        });

        $("a.downvote", footer).on("click", function() {
            api.dislike(comment.id).then(function(rv) {
                votes(rv.likes - rv.dislikes);
            });
        });

        $("a.edit", footer).toggle("click",
            function(toggler) {
                var edit = $("a.edit", footer);

                edit.textContent = msgs["comment-save"];
                edit.insertAfter($.new("a.cancel", msgs["comment-cancel"])).on("click", function() {
                    text.textContent = "";
                    text.className = "text";
                    text.append(comment.text);
                    toggler.next();
                });

                api.view(comment.id, 1).then(function(rv) {
                    var textarea = $.new("textarea", rv.text);
                    fancy.autoresize(textarea, 48);
                    text.className = "textarea-wrapper";
                    text.textContent = "";
                    text.append(textarea);
                    textarea.focus();
                });
            },
            function(toggler) {
                var textarea = $("textarea", text);
                if (textarea && textarea.value.length < 3) {
                    textarea.focus();
                    toggler.wait();
                    return;
                } else if (textarea) {
                    api.modify(comment.id, {"text": textarea.value}).then(function(rv) {
                        text.innerHTML = rv.text;
                        text.className = "text";
                        comment.text = rv.text;
                    });
                }

                $("a.cancel", footer).remove();
                $("a.edit", footer).textContent = msgs["comment-edit"];
            }
        );

        $("a.delete", footer).toggle("click",
            function(toggler) {
                var del = $("a.delete", footer);
                var state = ! toggler.state;

                del.textContent = msgs["comment-confirm"];
                del.on("mouseout", function() {
                    del.textContent = msgs["comment-delete"];
                    toggler.state = state;
                    del.onmouseout = null;
                });
            },
            function() {
                var del = $("a.delete", footer);
                api.remove(comment.id).then(function(rv) {
                    if (rv) {
                        el.remove();
                    } else {
                        $("span.note", header).textContent = msgs["comment-deleted"];
                        text.innerHTML = "

";
                    }
                    del.textContent = msgs["comment-delete"];
                });
            }
        );

        // remove edit and delete buttons when cookie is gone
        var clear = function(button) {
            if (! utils.cookie(comment.id)) {
                $(button, footer).remove();
            } else {
                setTimeout(function() { clear(button); }, 15*1000);
            }
        };

        clear("a.edit");
        clear("a.delete");

        // show direct reply to own comment when cookie is max aged
        var show = function(el) {
            if (utils.cookie(comment.id)) {
                setTimeout(function() { show(el); }, 15*1000);
            } else {
                footer.append(el);
            }
        };

        if (utils.cookie(comment.id)) {
            show($("a.reply", footer).detach());
        }
    };

    return {
        insert: insert,
        Postbox: Postbox
    };
});<|endoftext|>


<commit_before>import AppBar from '@material-ui/core/AppBar'
import Button from '@material-ui/core/Button'
import Card from '@material-ui/core/Card'
import CardActions from '@material-ui/core/CardActions'
import CardContent from '@material-ui/core/CardContent'
import IconButton from '@material-ui/core/IconButton'
import LockIcon from '@material-ui/icons/Lock'
import NavigatorLanguagesParser from 'navigator-languages-parser'
import { FormattedMessage, IntlProvider } from 'react-intl'
import React, { useEffect } from 'react'
import Toolbar from '@material-ui/core/Toolbar'
import Tooltip from '@material-ui/core/Tooltip'
import Typography from '@material-ui/core/Typography'
import { GitHubIcon } from 'rmw-shell/lib/components/Icons'
import { Helmet } from 'react-helmet'
import { withRouter } from 'react-router-dom'
import { withStyles } from '@material-ui/core/styles'
import messages_de from './de.json'
import messages_en from './en.json'
import messages_ru from './ru.json'
import messages_bs from './bs.json'
import messages_es from './es.json'

const messages = {
  'de': messages_de,
  'bs': messages_bs,
  'es': messages_es,
  'en': messages_en,
  'ru': messages_ru
};
const styles = theme => ({
  main: {
    display: 'flex',
    flexDirection: 'column'
  },
  root: {
    flexGrow: 1,
    flex: '1 0 100%'
    // height: '100%',
    // overflow: 'hidden'
  },
  hero: {
    height: '100%',
    // minHeight: '80vh',
    flex: '0 0 auto',
    display: 'flex',
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: theme.palette.background.paper,
    color: theme.palette.type === 'light' ? theme.palette.primary.dark : theme.palette.primary.main
  },
  text: {
    display: 'flex',
    flexDirection: 'column',
    alignItems: 'center',
    justifyContent: 'center'
  },
  title: {
    letterSpacing: '.7rem',
    textIndent: '.7rem',
    fontWeight: theme.typography.fontWeightLight,
    [theme.breakpoints.only('xs')]: {
      fontSize: 24,
      letterSpacing: '.1em',
      textIndent: '.1rem'
    },
    whiteSpace: 'nowrap'
  },
  h5: {
    paddingLeft: theme.spacing(1) * 4,
    paddingRight: theme.spacing(1) * 4,
    marginTop: theme.spacing(1),
    maxWidth: 600,
    textAlign: 'center',
    [theme.breakpoints.only('xs')]: {
      fontSize: 18
    }
  },
  content: {
    height: '100%',
    // paddingTop: theme.spacing(1) * 8,
    [theme.breakpoints.up('sm')]: {
      paddingTop: theme.spacing(1)
    }
  },
  button: {
    marginTop: theme.spacing(1) * 3
  },
  logo: {
    color: 'red',
    margin: `${theme.spacing(1) * 3}px 0 ${theme.spacing(1) * 4}px`,
    width: '100%',
    height: '40vw',
    maxHeight: 250
  },
  steps: {
    maxWidth: theme.spacing(1) * 130,
    margin: 'auto'
  },
  step: {
    padding: `${theme.spacing(1) * 3}px ${theme.spacing(1) * 2}px`
  },
  stepIcon: {
    marginBottom: theme.spacing(1)
  },
  markdownElement: {},
  cardsContent: {
    padding: 15,
    display: 'flex',
    justifyContent: 'space-around',
    flexWrap: 'wrap',
    [theme.breakpoints.only('xs')]: {
      width: '100%',
      padding: 0,
      paddingTop: 15
    }
  },
  card: {
    minWidth: 275,
    maxWidth: 350,
    margin: 15,
    [theme.breakpoints.only('xs')]: {
      width: '100%',
      margin: 0,
      marginTop: 7
    }
  },
  bullet: {
    display: 'inline-block',
    margin: '0 2px',
    transform: 'scale(0.8)'
  },
  cardTitle: {
    marginBottom: 16,
    fontSize: 14
  },
  pos: {
    marginBottom: 12
  }
})
const match = NavigatorLanguagesParser.parseLanguages(['en', 'es', 'bs','ru', 'de'], 'en')
const LandingPage = ({ props, classes, history, theme }) => {
  const [locale] = React.useState(match);
  const isAuthorised = () => {
    try {
      const key = Object.keys(localStorage).find(e => e.match(/persist:root/))
      const data = JSON.parse(localStorage.getItem(key))
      const auth = JSON.parse(data.auth)

      return auth && auth.isAuthorised
    } catch (ex) {
      return false
    }
  }

  useEffect(() => {
    if (isAuthorised()) {
      history.push('/signin')
    }
  })

  return (
    <IntlProvider locale={ locale } messages={ messages[locale] }>

    <FormattedMessage id="main.title">
      {title =><Helmet>
        <meta name="theme-color" content={theme.palette.primary.main} />
        <meta name="apple-mobile-web-app-status-bar-style" content={theme.palette.primary.main} />
        <meta name="msapplication-navbutton-color" content={theme.palette.primary.main} />
        <title>{title}</title>
      </Helmet>}
    </FormattedMessage>
      <AppBar position="static">
        <Toolbar disableGutters>

          <Tooltip id="tooltip-icon1" title="Sign in">
            <IconButton
              name="signin"
              aria-label="Open Github"
              color="inherit"
              onClick={() => {
                history.push('/signin')
              }}
              rel="noopener"
            >
              <LockIcon />
            </IconButton>
          </Tooltip>
          <Tooltip id="tooltip-icon2" title="GitHub repository">
            <IconButton
              name="github"
              aria-label="Open Github"
              color="inherit"
              href="https://github.com/TarikHuber/react-most-wanted"
              target="_blank"
              rel="noopener"
            >
              <GitHubIcon />
            </IconButton>
          </Tooltip>
        </Toolbar>
      </AppBar>

              <Typography
                variant="h3"
                align="center"
                component="h1"
                color="inherit"
                gutterBottom
                className={classes.title}
              >
                {'REACT MOST WANTED'}
              </Typography>
              <Typography variant="h5" component="h2" color="inherit" gutterBottom className={classes.h5}>
               <FormattedMessage id="main.intro" />
              </Typography>
              <Button
                onClick={() => {
                  history.push('/signin')
                }}
                className={classes.button}
                variant="outlined"
                color="primary"
              >
                {'Get Started'}
              </Button>

              <Card className={classes.card}>
                <CardContent>
                  <Typography variant="h5" component="h2">
                    Installation
                  </Typography>

                  <Typography>{'Just run this script to start:'}</Typography>

                  <Typography className={classes.pos} color="textSecondary">
                    {' '}
                    npx create-react-app test-app --scripts-version rmw-react-scripts{' '}
                  </Typography>
                </CardContent>
                <CardActions>
                  <Button
                    size="small"
                    onClick={() => {
                      var win = window.open('https://github.com/TarikHuber/rmw-shell', '_blank')
                      win.focus()
                    }}
                  >
                    Learn More
                  </Button>
                </CardActions>
              </Card>
              <Card className={classes.card}>
                <CardContent>
                  <Typography variant="h5" component="h2">
                    Usage
                  </Typography>

                  <Typography>{'Set your configuration to the App component:'}</Typography>

                  <Typography className={classes.pos} color="textSecondary">
                    {'import App from \'rmw-shell\''}

                    {'<App appConfig={{ configureStore, ...config }} />'}
                  </Typography>
                </CardContent>
                <CardActions>
                  <Button
                    size="small"
                    onClick={() => {
                      var win = window.open('https://github.com/TarikHuber/react-most-wanted', '_blank')
                      win.focus()
                    }}
                  >
                    Learn More
                  </Button>
                </CardActions>
              </Card>
              <Card className={classes.card}>
                <CardContent>
                  <Typography variant="h5" component="h2">
                    What is this?
                  </Typography>
                  <Typography noWrap={false} color="textSecondary">
                    {`This is a OPEN SOURCE demo application that demonstartes the usage of the rmw-shell library
                    with react, Material-UI and firebase.  `}

                    {` This demo has no purpose to do something as an app.
                    It is here just to show how everthing works together. `}
                  </Typography>
                </CardContent>
                <CardActions>
                  <Button
                    size="small"
                    onClick={() => {
                      history.push('/signin')
                    }}
                  >
                    Get started
                  </Button>
                </CardActions>
              </Card>

   </IntlProvider>
  )
}

export default withRouter(withStyles(styles, { withTheme: true })(LandingPage))
<commit_msg>LandingPage Internationalization<commit_after>import AppBar from '@material-ui/core/AppBar'
import Button from '@material-ui/core/Button'
import Card from '@material-ui/core/Card'
import CardActions from '@material-ui/core/CardActions'
import CardContent from '@material-ui/core/CardContent'
import IconButton from '@material-ui/core/IconButton'
import LockIcon from '@material-ui/icons/Lock'
import NavigatorLanguagesParser from 'navigator-languages-parser'
import { FormattedMessage, IntlProvider } from 'react-intl'
import React, { useEffect } from 'react'
import Toolbar from '@material-ui/core/Toolbar'
import Tooltip from '@material-ui/core/Tooltip'
import Typography from '@material-ui/core/Typography'
import { GitHubIcon } from 'rmw-shell/lib/components/Icons'
import { Helmet } from 'react-helmet'
import { withRouter } from 'react-router-dom'
import { withStyles } from '@material-ui/core/styles'
import messages_de from './de.json'
import messages_en from './en.json'
import messages_ru from './ru.json'
import messages_bs from './bs.json'
import messages_es from './es.json'

const messages = {
  'de': messages_de,
  'bs': messages_bs,
  'es': messages_es,
  'en': messages_en,
  'ru': messages_ru
};
const styles = theme => ({
  main: {
    display: 'flex',
    flexDirection: 'column'
  },
  root: {
    flexGrow: 1,
    flex: '1 0 100%'
    // height: '100%',
    // overflow: 'hidden'
  },
  hero: {
    height: '100%',
    // minHeight: '80vh',
    flex: '0 0 auto',
    display: 'flex',
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: theme.palette.background.paper,
    color: theme.palette.type === 'light' ? theme.palette.primary.dark : theme.palette.primary.main
  },
  text: {
    display: 'flex',
    flexDirection: 'column',
    alignItems: 'center',
    justifyContent: 'center'
  },
  title: {
    letterSpacing: '.7rem',
    textIndent: '.7rem',
    fontWeight: theme.typography.fontWeightLight,
    [theme.breakpoints.only('xs')]: {
      fontSize: 24,
      letterSpacing: '.1em',
      textIndent: '.1rem'
    },
    whiteSpace: 'nowrap'
  },
  h5: {
    paddingLeft: theme.spacing(1) * 4,
    paddingRight: theme.spacing(1) * 4,
    marginTop: theme.spacing(1),
    maxWidth: 600,
    textAlign: 'center',
    [theme.breakpoints.only('xs')]: {
      fontSize: 18
    }
  },
  content: {
    height: '100%',
    // paddingTop: theme.spacing(1) * 8,
    [theme.breakpoints.up('sm')]: {
      paddingTop: theme.spacing(1)
    }
  },
  button: {
    marginTop: theme.spacing(1) * 3
  },
  logo: {
    color: 'red',
    margin: `${theme.spacing(1) * 3}px 0 ${theme.spacing(1) * 4}px`,
    width: '100%',
    height: '40vw',
    maxHeight: 250
  },
  steps: {
    maxWidth: theme.spacing(1) * 130,
    margin: 'auto'
  },
  step: {
    padding: `${theme.spacing(1) * 3}px ${theme.spacing(1) * 2}px`
  },
  stepIcon: {
    marginBottom: theme.spacing(1)
  },
  markdownElement: {},
  cardsContent: {
    padding: 15,
    display: 'flex',
    justifyContent: 'space-around',
    flexWrap: 'wrap',
    [theme.breakpoints.only('xs')]: {
      width: '100%',
      padding: 0,
      paddingTop: 15
    }
  },
  card: {
    minWidth: 275,
    maxWidth: 350,
    margin: 15,
    [theme.breakpoints.only('xs')]: {
      width: '100%',
      margin: 0,
      marginTop: 7
    }
  },
  bullet: {
    display: 'inline-block',
    margin: '0 2px',
    transform: 'scale(0.8)'
  },
  cardTitle: {
    marginBottom: 16,
    fontSize: 14
  },
  pos: {
    marginBottom: 12
  }
})
const match = NavigatorLanguagesParser.parseLanguages(['en', 'es', 'bs','ru', 'de'], 'en')
const LandingPage = ({ props, classes, history, theme }) => {
  const [locale] = React.useState(match);
  const isAuthorised = () => {
    try {
      const key = Object.keys(localStorage).find(e => e.match(/persist:root/))
      const data = JSON.parse(localStorage.getItem(key))
      const auth = JSON.parse(data.auth)

      return auth && auth.isAuthorised
    } catch (ex) {
      return false
    }
  }

  useEffect(() => {
    if (isAuthorised()) {
      history.push('/signin')
    }
  })

  return (
    <IntlProvider locale={ locale } messages={ messages[locale] }>

    <FormattedMessage id="main.title">
      {title =><Helmet>
        <meta name="theme-color" content={theme.palette.primary.main} />
        <meta name="apple-mobile-web-app-status-bar-style" content={theme.palette.primary.main} />
        <meta name="msapplication-navbutton-color" content={theme.palette.primary.main} />
        <title>{title}</title>
      </Helmet>}
    </FormattedMessage>
      <AppBar position="static">
        <Toolbar disableGutters>

          <Tooltip id="tooltip-icon1" title="Sign in">
            <IconButton
              name="signin"
              aria-label="Open Github"
              color="inherit"
              onClick={() => {
                history.push('/signin')
              }}
              rel="noopener"
            >
              <LockIcon />
            </IconButton>
          </Tooltip>
          <Tooltip id="tooltip-icon2" title="GitHub repository">
            <IconButton
              name="github"
              aria-label="Open Github"
              color="inherit"
              href="https://github.com/TarikHuber/react-most-wanted"
              target="_blank"
              rel="noopener"
            >
              <GitHubIcon />
            </IconButton>
          </Tooltip>
        </Toolbar>
      </AppBar>

              <Typography
                variant="h3"
                align="center"
                component="h1"
                color="inherit"
                gutterBottom
                className={classes.title}
              >
                <FormattedMessage id="main.title" />
              </Typography>
              <Typography variant="h5" component="h2" color="inherit" gutterBottom className={classes.h5}>
               <FormattedMessage id="main.intro" />
              </Typography>
              <Button
                onClick={() => {
                  history.push('/signin')
                }}
                className={classes.button}
                variant="outlined"
                color="primary"
              >
                {'Get Started'}
              </Button>

              <Card className={classes.card}>
                <CardContent>
                  <Typography variant="h5" component="h2">
                    Installation
                  </Typography>

                  <Typography>{'Just run this script to start:'}</Typography>

                  <Typography className={classes.pos} color="textSecondary">
                    {' '}
                    npx create-react-app test-app --scripts-version rmw-react-scripts{' '}
                  </Typography>
                </CardContent>
                <CardActions>
                  <Button
                    size="small"
                    onClick={() => {
                      var win = window.open('https://github.com/TarikHuber/rmw-shell', '_blank')
                      win.focus()
                    }}
                  >
                    Learn More
                  </Button>
                </CardActions>
              </Card>
              <Card className={classes.card}>
                <CardContent>
                  <Typography variant="h5" component="h2">
                    Usage
                  </Typography>

                  <Typography>{'Set your configuration to the App component:'}</Typography>

                  <Typography className={classes.pos} color="textSecondary">
                    {'import App from \'rmw-shell\''}

                    {'<App appConfig={{ configureStore, ...config }} />'}
                  </Typography>
                </CardContent>
                <CardActions>
                  <Button
                    size="small"
                    onClick={() => {
                      var win = window.open('https://github.com/TarikHuber/react-most-wanted', '_blank')
                      win.focus()
                    }}
                  >
                    Learn More
                  </Button>
                </CardActions>
              </Card>
              <Card className={classes.card}>
                <CardContent>
                  <Typography variant="h5" component="h2">
                    What is this?
                  </Typography>
                  <Typography noWrap={false} color="textSecondary">
                    {`This is a OPEN SOURCE demo application that demonstartes the usage of the rmw-shell library
                    with react, Material-UI and firebase.  `}

                    {` This demo has no purpose to do something as an app.
                    It is here just to show how everthing works together. `}
                  </Typography>
                </CardContent>
                <CardActions>
                  <Button
                    size="small"
                    onClick={() => {
                      history.push('/signin')
                    }}
                  >
                    Get started
                  </Button>
                </CardActions>
              </Card>

   </IntlProvider>
  )
}

export default withRouter(withStyles(styles, { withTheme: true })(LandingPage))
<|endoftext|>


<commit_before>import _ from 'lodash'

const SortChannels = (channels, sort, reverse = false) => {
    let sortedChannels = [];

    switch (sort) {
        case 'lastAdded': {
            sortedChannels = channels;
            break;
        }
        case 'lastUpdated': {
            sortedChannels = _.sortBy(channels, ['lastUpdated']);
            break;
        }
        case 'service_visibleName': {
            sortedChannels = _.sortBy(channels, ['service', 'visibleName']);
            break;
        }
        case 'visibleName': {
            sortedChannels = _.sortBy(channels, ['visibleName']);
            break;
        }
        default: {
            sortedChannels = channels;
        }
    }

    if (reverse) {
        sortedChannels.reverse();
    }

    return sortedChannels;
};

export default SortChannels;
<commit_msg>Sorting pinned support.<commit_after>import _ from 'lodash'

const SortChannels = (channels, sortType, isReversed = false) => {
    let sortedChannels = [];

    switch (sortType) {
        case 'lastAdded': {
            sortedChannels = channels;
            break;
        }
        case 'lastUpdated': {
            sortedChannels = _.sortBy(channels, ['lastUpdated']);
            break;
        }
        case 'service_visibleName': {
            sortedChannels = _.sortBy(channels, ['service', 'visibleName']);
            break;
        }
        case 'visibleName': {
            sortedChannels = _.sortBy(channels, ['visibleName']);
            break;
        }
        default: {
            sortedChannels = channels;
        }
    }

    if (isReversed) {
        sortedChannels.reverse();
    }

    sortedChannels = _.sortBy(sortedChannels, [(channel) => !channel.isPinned]);

    return sortedChannels;
};

export default SortChannels;
<|endoftext|>


<commit_before>MutationObserver = window.MutationObserver || window.WebKitMutationObserver
var observer = new MutationObserver(function(mutations, observer) {
    jQuery(".UFILikeLink").each(function() {
        if(this.dataset.ft == '{"tn":">"}') {
            $(this).html("朕知道了")
        }
        else if(this.dataset.ft == '{"tn":"?"}') {
            $(this).html("朕也是看報紙才知道")
        }
    })
    jQuery(".uiLinkButtonInput").each(function() {
        if ( $(this).text() == "Comment" || $(this).text() == "回應" ) {
			$(this).text("卿家可知？")
        }
    })
    jQuery(".share_action_link").each(function() {
        if ($(this).text() == "Share" || $(this).text() == "分享") {
            $(this).text("宣旨")
        }
    })
})

observer.observe(document, {
    subtree: true,
    attributes: true
})
<commit_msg>update comment button<commit_after>MutationObserver = window.MutationObserver || window.WebKitMutationObserver
var observer = new MutationObserver(function(mutations, observer) {
    jQuery(".UFILikeLink").each(function() {
        if(this.dataset.ft == '{"tn":">"}') {
            $(this).html("朕知道了")
        }
        else if(this.dataset.ft == '{"tn":"?"}') {
            $(this).html("朕也是看報紙才知道")
        }
    })
    jQuery(".comment_link > span").each(function() {
		$(this).text("卿家可知？")
    })
    jQuery(".share_action_link").each(function() {
        if ($(this).text() == "Share" || $(this).text() == "分享") {
            $(this).text("宣旨")
        }
    })
})

observer.observe(document, {
    subtree: true,
    attributes: true
})
<|endoftext|>


<commit_before>'use strict';
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/TTKHospital');
var moment = require('moment');

var people = require('../model/people');
var DailyCallsModel = require('../model/dailyCalls');

DailyCallsModel.find({}, function(err, data) {
    if (err) {
        console.log("DB error while fetching all data\n");
    } else {
        processCalls(data);
    }
});

function processCalls(peopleArr) {
    for (var i = 0; i < peopleArr.length; i++)
        people.findOne({
            id: peopleArr[i].personId
        }, function(err, doc) {
            if (err) {
                console.log(err);
                return;
            } else {
                processPersonCallRecords(doc);
            }
        });
}

function processPersonCallRecords(person) {
    console.log(person);
    var calls = person.calls,
        i;
    var today = moment().format("MM/DD/YY");
    var updateObj = {};
    if(calls.length == 0){
        updateObj.failedContactCount = person.failedContactCount + 1;
    }
    else{
        if (moment(calls[calls.length - 1].time).format("MM/DD/YY") !== today) {
            console.log("For " + person.person.phone + " no call today");
            updateObj.failedContactCount = person.failedContactCount + 1;
        } else {
            var status1 = calls[calls.length - 1].response;
            var status2 = 0;
            if (calls.length > 1 && moment(calls[calls.length - 2].time).format("MM/DD/YY") === today) {
                //Last 2 calls have been successful and been made today
                status2 = calls[calls.length - 2].response;
            }
            updateObj.status = Math.max(status1, status2);
        }

        for (i = 0; i < calls.length; i++) {

        }
    }
    console.log(updateObj);
    people.findOneAndUpdate({
        id: person.id
    }, {
        $set: updateObj
    }, function(err, updateRes) {
        if (err) {
            console.log("Error while updating " + err);
        } else {
            console.log(updateRes);
        }
    });

}
<commit_msg>Process call<commit_after>'use strict';
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/TTKHospital');
var moment = require('moment');

var people = require('../model/people');
var DailyCallsModel = require('../model/dailyCalls');

var ivrConfig = require('./ivrConfig.js');

DailyCallsModel.find({}, function(err, data) {
    if (err) {
        console.log("DB error while fetching all data\n");
    } else {
        processCalls(data);
    }
});

function processCalls(peopleArr) {
    for (var i = 0; i < peopleArr.length; i++)
        people.findOne({
            id: peopleArr[i].personId
        }, function(err, doc) {
            if (err) {
                console.log(err);
                return;
            } else {
                processPersonCallRecords(doc);
            }
        });
}

function processPersonCallRecords(person) {
    console.log(person);
    var calls = person.calls,
        i;
    var today = moment().format("MM/DD/YY");
    var updateObj = {};
    updateObj.bucket = person.bucket;
    if (calls.length == 0) {
        updateObj.failedContactCount = person.failedContactCount + 1;
    } else {
        if (moment(calls[calls.length - 1].time).format("MM/DD/YY") !== today) {
            console.log("For " + person.person.phone + " no call today");
            updateObj.failedContactCount = person.failedContactCount + 1;
        } else {
            var status1 = calls[calls.length - 1].response;
            var status2 = 0;
            if (calls.length > 1 && moment(calls[calls.length - 2].time).format("MM/DD/YY") === today) {
                //Last 2 calls have been successful and been made today
                status2 = calls[calls.length - 2].response;
            }
            updateObj.status = Math.max(status1, status2);
        }
        var uniqueDates = {};
        for (i = calls.length - 1; i >= 0; i--) {
            if (person.bucket !== calls[i].bucket)
                break;
            uniqueDates[calls[i].bucket] = true;
        }
        if (person.bucket < ivrConfig.length && Object.keys(uniqueDates).length >= ivrConfig[person.bucket].promotionCount) {
            updateObj.bucket = person.bucket++;
        }
    }
    updateObj.nextCallDate = (person.bucket === ivrConfig.length)? 0 : person.nextCallDate + (ivrConfig[updateObj.bucket].callingFrequency * 24 * 60 * 60);
    console.log(updateObj);
    people.findOneAndUpdate({
        id: person.id
    }, {
        $set: updateObj
    }, function(err, updateRes) {
        if (err) {
            console.log("Error while updating " + err);
        } else {
            console.log(updateRes);
        }
    });

}
<|endoftext|>


<commit_before>app.config([
  'formioComponentsProvider',
  function(formioComponentsProvider) {
    formioComponentsProvider.register('datetime', {
      views: [
        {
          name: 'Display',
          template: 'formio/components/datetime/display.html'
        },
        {
          name: 'Validation',
          template: 'formio/components/datetime/validate.html'
        },
        {
          name: 'API',
          template: 'formio/components/datetime/api.html'
        }
      ]
    });
  }
]);
app.run([
  '$templateCache',
  function($templateCache) {

    // Create the settings markup.
    $templateCache.put('formio/components/datetime/display.html',
      '<ng-form>' +
        '
' +
          'Label' +
          '<input type="text" class="form-control" id="label" name="label" ng-model="component.label" placeholder="Field Label" value="{{ component.label }}">' +
        '
' +
        '
' +
          'Place Holder' +
          '<input type="text" class="form-control" id="placeholder" name="placeholder" ng-model="component.placeholder" placeholder="Placeholder" value="{{ component.placeholder }}">' +
        '
' +
        '
' +
          'Minute Step' +
          '<input type="number" class="form-control" id="minuteStep" name="minuteStep" ng-model="component.minuteStep" placeholder="Minute Step" value="{{ component.minuteStep }}" min="1" max="59">' +
        '
' +
        '
' +
          '' +
            '<input type="checkbox" id="protected" name="protected" ng-model="component.protected" ng-checked="component.protected"> Protected' +
          '' +
        '
' +
        '
' +
          '' +
            '<input type="checkbox" id="persistent" name="persistent" ng-model="component.persistent" ng-checked="component.persistent"> Persistent' +
          '' +
        '
' +
      '</ng-form>'
    );

    // Create the API markup.
    $templateCache.put('formio/components/datetime/api.html',
      '<ng-form>' +
        '
' +
          'Property Name' +
          '<input type="text" class="form-control" id="key" name="key" ng-model="component.key" value="{{ component.key }}" ng-blur="component.lockKey = true;" ng-required>' +
        '
' +
      '</ng-form>'
    );

    // Create the API markup.
    $templateCache.put('formio/components/datetime/validate.html',
      '<ng-form>' +
        '
' +
          '' +
            '<input type="checkbox" id="required" name="required" ng-model="component.validate.required" ng-checked="component.validate.required"> Required' +
          '' +
        '
' +
        '
' +
          '
Custom Validation
' +
          '
' +
            '<textarea class="form-control" rows="5" id="custom" name="custom" ng-model="component.validate.custom" placeholder="/*** Example Code ***/\nvalid = (input === 3) ? true : \'Must be 3\';">{{ component.validate.custom }}</textarea>' +
            '
Enter custom validation code.
' +
            '
You must assign the valid variable as either true or an error message if validation fails.
' +
            '
The global variables input, component, and valid are provided.
' +
            '
' +
              '
' +
                '' +
                  '<input type="checkbox" id="private" name="private" ng-model="component.validate.customPrivate" ng-checked="component.validate.customPrivate"> Secret Validation' +
                '' +
              '
' +
              '
Check this if you wish to perform the validation ONLY on the server side. This keeps your validation logic private and secret.
' +
            '
' +
          '
' +
        '
' +
      '</ng-form>'
    );
  }
]);
<commit_msg>Temporarily removing datetime component<commit_after>app.config([
  'formioComponentsProvider',
  function(formioComponentsProvider) {
    // formioComponentsProvider.register('datetime', {
    //   views: [
    //     {
    //       name: 'Display',
    //       template: 'formio/components/datetime/display.html'
    //     },
    //     {
    //       name: 'Validation',
    //       template: 'formio/components/datetime/validate.html'
    //     },
    //     {
    //       name: 'API',
    //       template: 'formio/components/datetime/api.html'
    //     }
    //   ]
    // });
  }
]);
app.run([
  '$templateCache',
  function($templateCache) {

    // Create the settings markup.
    $templateCache.put('formio/components/datetime/display.html',
      '<ng-form>' +
        '
' +
          'Label' +
          '<input type="text" class="form-control" id="label" name="label" ng-model="component.label" placeholder="Field Label" value="{{ component.label }}">' +
        '
' +
        '
' +
          'Place Holder' +
          '<input type="text" class="form-control" id="placeholder" name="placeholder" ng-model="component.placeholder" placeholder="Placeholder" value="{{ component.placeholder }}">' +
        '
' +
        '
' +
          'Minute Step' +
          '<input type="number" class="form-control" id="minuteStep" name="minuteStep" ng-model="component.minuteStep" placeholder="Minute Step" value="{{ component.minuteStep }}" min="1" max="59">' +
        '
' +
        '
' +
          '' +
            '<input type="checkbox" id="protected" name="protected" ng-model="component.protected" ng-checked="component.protected"> Protected' +
          '' +
        '
' +
        '
' +
          '' +
            '<input type="checkbox" id="persistent" name="persistent" ng-model="component.persistent" ng-checked="component.persistent"> Persistent' +
          '' +
        '
' +
      '</ng-form>'
    );

    // Create the API markup.
    $templateCache.put('formio/components/datetime/api.html',
      '<ng-form>' +
        '
' +
          'Property Name' +
          '<input type="text" class="form-control" id="key" name="key" ng-model="component.key" value="{{ component.key }}" ng-blur="component.lockKey = true;" ng-required>' +
        '
' +
      '</ng-form>'
    );

    // Create the API markup.
    $templateCache.put('formio/components/datetime/validate.html',
      '<ng-form>' +
        '
' +
          '' +
            '<input type="checkbox" id="required" name="required" ng-model="component.validate.required" ng-checked="component.validate.required"> Required' +
          '' +
        '
' +
        '
' +
          '
Custom Validation
' +
          '
' +
            '<textarea class="form-control" rows="5" id="custom" name="custom" ng-model="component.validate.custom" placeholder="/*** Example Code ***/\nvalid = (input === 3) ? true : \'Must be 3\';">{{ component.validate.custom }}</textarea>' +
            '
Enter custom validation code.
' +
            '
You must assign the valid variable as either true or an error message if validation fails.
' +
            '
The global variables input, component, and valid are provided.
' +
            '
' +
              '
' +
                '' +
                  '<input type="checkbox" id="private" name="private" ng-model="component.validate.customPrivate" ng-checked="component.validate.customPrivate"> Secret Validation' +
                '' +
              '
' +
              '
Check this if you wish to perform the validation ONLY on the server side. This keeps your validation logic private and secret.
' +
            '
' +
          '
' +
        '
' +
      '</ng-form>'
    );
  }
]);<|endoftext|>


<commit_before>'use strict';
module.exports = function() { // eslint-disable-line func-names
  // Global variables
  const gulp    = this.gulp,
        plugins = this.opts.plugins,
        config  = this.opts.configs,
        themes  = plugins.getThemes();

  themes.forEach(name => {
    const theme = config.themes[name],
          srcBase = config.projectPath + 'var/view_preprocessed/frontools' + theme.dest.replace('pub/static', '');

    // For theme without per locale overwrites  - most of cases
    if (!theme.localeOverwrites) {
      plugins.util.log(
        plugins.util.colors.green('Watching theme:') + ' '
        + plugins.util.colors.blue(name) + ' '
        + plugins.util.colors.green('Locale:') + ' '
        + plugins.util.colors.blue(theme.locale.join(' ')) + ' '
        + plugins.util.colors.green('and dependencies...')
      );

      const files = plugins.globby.sync([
              srcBase + '/**/*.scss',
              '!/**/_*.scss',
              '!**/node_modules/**'
            ]),
            dependencyTreeBuilder = require('../helper/dependency-tree-builder');

      files.forEach(file => {
        gulp.watch(
          Array.from(new Set(dependencyTreeBuilder(theme, file, plugins))),
          event => {
            plugins.util.log(
              plugins.util.colors.green('File') + ' '
              + plugins.util.colors.blue(event.path.replace(config.projectPath + 'var/view_preprocessed/frontools', '')) + ' '
              + plugins.util.colors.green('changed.')
            );
            require('../helper/scss')(gulp, plugins, config, name, file);
          }
        );
      });
    }
    // For themes with per locale overwrites
    else {
      theme.locale.forEach(locale => {
        plugins.util.log(
          plugins.util.colors.green('Watching theme:') + ' '
          + plugins.util.colors.blue(name) + ' '
          + plugins.util.colors.green('Locale:') + ' '
          + plugins.util.colors.blue(locale) + ' '
          + plugins.util.colors.green('and dependencies...')
        );

        const files = plugins.globby.sync([
                srcBase + '/' + locale + '/**/*.scss',
                '!/**/_*.scss',
                '!**/node_modules/**'
              ]),
              dependencyTreeBuilder = require('../helper/dependency-tree-builder');

        files.forEach(file => {
          gulp.watch(
            Array.from(new Set(dependencyTreeBuilder(theme, file, plugins))),
            event => {
              plugins.util.log(
                plugins.util.colors.green('File') + ' '
                + plugins.util.colors.blue(event.path.replace(config.projectPath + 'var/view_preprocessed/frontools', '')) + ' '
                + plugins.util.colors.green('changed.')
              );
              require('../helper/scss')(gulp, plugins, config, name, file)
            }
          );
        });
      });
    }

    if (!plugins.util.env.disableLinting) {
      // SASS Lint
      gulp.watch(plugins.globby.sync(srcBase + '/**/*.scss'), event => {
        require('../helper/sass-lint')(gulp, plugins, config, name, event.path);
      });
      // CSS Lint
      gulp.watch(plugins.globby.sync(config.projectPath + theme.dest + '/**/*.css'), event => {
        require('../helper/css-lint')(gulp, plugins, config, name, event.path);
      });
    }

    // Watching files that require reload after save
    gulp.watch(
      // I'm usng globby manually, b/c it's a loooot faster
      plugins.globby.sync([
        config.projectPath + theme.src + '/**/*.{html,phtml,xml,csv,js}',
        '!/**/node_modules/**'
      ]),
      event => {
        plugins.util.log(
          plugins.util.colors.green('File') + ' '
          + plugins.util.colors.blue(event.path.replace(config.projectPath, '')) + ' '
          + plugins.util.colors.green('changed.')
        );
        plugins.browserSync.reload();
      }
    );
  });
};
<commit_msg>Babel added to watch task<commit_after>'use strict';
module.exports = function() { // eslint-disable-line func-names
  // Global variables
  const gulp    = this.gulp,
        plugins = this.opts.plugins,
        config  = this.opts.configs,
        themes  = plugins.getThemes();

  themes.forEach(name => {
    const theme = config.themes[name],
          srcBase = config.projectPath + 'var/view_preprocessed/frontools' + theme.dest.replace('pub/static', '');

    // For theme without per locale overwrites  - most of cases
    if (!theme.localeOverwrites) {
      plugins.util.log(
        plugins.util.colors.green('Watching theme:') + ' '
        + plugins.util.colors.blue(name) + ' '
        + plugins.util.colors.green('Locale:') + ' '
        + plugins.util.colors.blue(theme.locale.join(' ')) + ' '
        + plugins.util.colors.green('and dependencies...')
      );

      const files = plugins.globby.sync([
              srcBase + '/**/*.scss',
              '!/**/_*.scss',
              '!**/node_modules/**'
            ]),
            dependencyTreeBuilder = require('../helper/dependency-tree-builder');

      files.forEach(file => {
        gulp.watch(
          Array.from(new Set(dependencyTreeBuilder(theme, file, plugins))),
          event => {
            plugins.util.log(
              plugins.util.colors.green('File') + ' '
              + plugins.util.colors.blue(event.path.replace(config.projectPath + 'var/view_preprocessed/frontools', '')) + ' '
              + plugins.util.colors.green('changed.')
            );
            require('../helper/scss')(gulp, plugins, config, name, file);
          }
        );
      });
    }
    // For themes with per locale overwrites
    else {
      theme.locale.forEach(locale => {
        plugins.util.log(
          plugins.util.colors.green('Watching theme:') + ' '
          + plugins.util.colors.blue(name) + ' '
          + plugins.util.colors.green('Locale:') + ' '
          + plugins.util.colors.blue(locale) + ' '
          + plugins.util.colors.green('and dependencies...')
        );

        const files = plugins.globby.sync([
                srcBase + '/' + locale + '/**/*.scss',
                '!/**/_*.scss',
                '!**/node_modules/**'
              ]),
              dependencyTreeBuilder = require('../helper/dependency-tree-builder');

        files.forEach(file => {
          gulp.watch(
            Array.from(new Set(dependencyTreeBuilder(theme, file, plugins))),
            event => {
              plugins.util.log(
                plugins.util.colors.green('File') + ' '
                + plugins.util.colors.blue(event.path.replace(config.projectPath + 'var/view_preprocessed/frontools', '')) + ' '
                + plugins.util.colors.green('changed.')
              );
              require('../helper/scss')(gulp, plugins, config, name, file)
            }
          );
        });
      });
    }

    if (!plugins.util.env.disableLinting) {
      // SASS Lint
      gulp.watch(plugins.globby.sync(srcBase + '/**/*.scss'), event => {
        require('../helper/sass-lint')(gulp, plugins, config, name, event.path);
      });
      // CSS Lint
      gulp.watch(plugins.globby.sync(config.projectPath + theme.dest + '/**/*.css'), event => {
        require('../helper/css-lint')(gulp, plugins, config, name, event.path);
      });
    }

    // Babel
    gulp.watch(plugins.globby.sync(srcBase + '/**/*.babel.js'), event => {
      plugins.util.log(
        plugins.util.colors.green('File') + ' '
        + plugins.util.colors.blue(event.path.replace(config.tempPath, '')) + ' '
        + plugins.util.colors.green('changed.')
      );
      require('../helper/babel')(gulp, plugins, config, name, event.path);
    });

    // Watching files that require reload after save
    gulp.watch(
      // I'm usng globby manually, b/c it's a loooot faster
      plugins.globby.sync([
        config.projectPath + theme.src + '/**/*.{html,phtml,xml,csv,js}',
        '!/**/*.babel.js'
      ]),
      event => {
        plugins.util.log(
          plugins.util.colors.green('File') + ' '
          + plugins.util.colors.blue(event.path.replace(config.projectPath, '')) + ' '
          + plugins.util.colors.green('changed.')
        );
        plugins.browserSync.reload();
      }
    );
  });
};
<|endoftext|>


<commit_before>// When Github page loads at repo path e.g. https://github.com/jquery/jquery, the HTML tree has
//  to contain server-rendered HTML in response of pjax.
// However, that  element doesn't have "id" attribute if the Github page loads at specific
// File e.g. https://github.com/jquery/jquery/blob/master/.editorconfig.
// Therefore, the below selector uses many path but only points to the same  element
const GH_PJAX_CONTAINER_SEL =
  '#js-repo-pjax-container, div[itemtype="http://schema.org/SoftwareSourceCode"] main, [data-pjax-container]';

const GH_CONTAINERS = '.container, .container-lg, .container-responsive';
const GH_HEADER = '.js-header-wrapper > header';
const GH_MAX_HUGE_REPOS_SIZE = 50;
const GH_HIDDEN_RESPONSIVE_CLASS = '.d-none';
const GH_RESPONSIVE_BREAKPOINT = 1010;

class GitHub extends PjaxAdapter {
  constructor(store) {
    super(store);
  }

  // @override
  init($sidebar) {
    const pjaxContainer = $(GH_PJAX_CONTAINER_SEL)[0];
    super.init($sidebar, {pjaxContainer: pjaxContainer});

    // Fix #151 by detecting when page layout is updated.
    // In this case, split-diff page has a wider layout, so need to recompute margin.
    // Note that couldn't do this in response to URL change, since new DOM via pjax might not be ready.
    const diffModeObserver = new window.MutationObserver((mutations) => {
      mutations.forEach((mutation) => {
        if (~mutation.oldValue.indexOf('split-diff') || ~mutation.target.className.indexOf('split-diff')) {
          return $(document).trigger(EVENT.LAYOUT_CHANGE);
        }
      });
    });

    diffModeObserver.observe(document.body, {
      attributes: true,
      attributeFilter: ['class'],
      attributeOldValue: true
    });
  }

  // @override
  getCssClass() {
    return 'octotree-github-sidebar';
  }

  // @override
  canLoadEntireTree(repo) {
    const key = `${repo.username}/${repo.reponame}`;
    const hugeRepos = this.store.get(STORE.HUGE_REPOS);
    if (hugeRepos[key]) {
      // Update the last load time of the repo
      hugeRepos[key] = new Date().getTime();
      this.store.set(STORE.HUGE_REPOS, hugeRepos);
    }
    return !hugeRepos[key];
  }

  // @override
  getCreateTokenUrl() {
    return (
      `${location.protocol}//${location.host}/settings/tokens/new?` +
      'scopes=repo&description=Octotree%20browser%20extension'
    );
  }

  // @override
  updateLayout(sidebarPinned, sidebarVisible, sidebarWidth) {
    const SPACING = 10;
    const $header = $(GH_HEADER);
    const $containers =
      $('html').width() <= GH_RESPONSIVE_BREAKPOINT
        ? $(GH_CONTAINERS).not(GH_HIDDEN_RESPONSIVE_CLASS)
        : $(GH_CONTAINERS);

    const autoMarginLeft = ($(document).width() - $containers.width()) / 2;
    const shouldPushEverything = sidebarPinned && sidebarVisible;
    const smallScreen = autoMarginLeft <= sidebarWidth + SPACING;

    $('html').css('margin-left', shouldPushEverything && smallScreen ? sidebarWidth : '');
    $containers.css('margin-left', shouldPushEverything && smallScreen ? SPACING : '');

    if (shouldPushEverything && !smallScreen) {
      // Override important in Github Header class in large screen
      $header.attr('style', `padding-left: ${sidebarWidth + SPACING}px !important`);
    } else {
      $header.removeAttr('style');
    }
  }

  // @override
  getRepoFromPath(currentRepo, token, cb) {
    if (!octotree.shouldShowOctotree()) {
      return cb();
    }

    // (username)/(reponame)[/(type)][/(typeId)]
    const match = window.location.pathname.match(/([^\/]+)\/([^\/]+)(?:\/([^\/]+))?(?:\/([^\/]+))?/);

    const username = match[1];
    const reponame = match[2];
    const type = match[3];
    const typeId = match[4];

    // Not a repository, skip
    if (~GH_RESERVED_USER_NAMES.indexOf(username) || ~GH_RESERVED_REPO_NAMES.indexOf(reponame)) {
      return cb();
    }

    // Get branch by inspecting URL or DOM, quite fragile so provide multiple fallbacks.
    // TODO would be great if there's a more robust way to do this
    /**
     * Github renders the branch name in one of below structure depending on the length
     * of branch name
     *
     * Option 1: when the length is short enough
     *
     *   feature/1/2/3
     *
     *
     * Option 2: when the length is too long
     *
     *   feature/1/2/3...
     *
     */
    const branchDropdownMenuSummary = $('.branch-select-menu summary');
    const branchNameInTitle = branchDropdownMenuSummary.attr('title');
    const branchNameInSpan = branchDropdownMenuSummary.find('span').text();
    const branchFromSummary =
      branchNameInTitle && branchNameInTitle.toLowerCase().startsWith('switch branches')
        ? branchNameInSpan
        : branchNameInTitle;

    const branch =
      // Pick the commit ID as branch name when the code page is listing tree in a particular commit
      (type === 'commit' && typeId) ||
      // Pick the commit ID or branch name from the DOM
      branchFromSummary ||
      ($('.overall-summary .numbers-summary .commits a').attr('href') || '').replace(
        `/${username}/${reponame}/commits/`,
        ''
      ) ||
      // Pull requests page
      ($('.commit-ref.base-ref').attr('title') || ':').match(/:(.*)/)[1] ||
      // Reuse last selected branch if exist
      (currentRepo.username === username && currentRepo.reponame === reponame && currentRepo.branch) ||
      // Get default branch from cache
      this._defaultBranch[username + '/' + reponame];

    const isPR = type === 'pull';
    const showOnlyChangedInPR = this.store.get(STORE.PR);
    const pullNumber = isPR && showOnlyChangedInPR ? typeId : null;
    const repo = {username, reponame, branch, pullNumber};
    if (repo.branch) {
      cb(null, repo);
    } else {
      // Still no luck, get default branch for real
      this._get(null, {repo, token}, (err, data) => {
        if (err) return cb(err);
        repo.branch = this._defaultBranch[username + '/' + reponame] = data.default_branch || 'master';
        cb(null, repo);
      });
    }
  }

  // @override
  selectFile(path) {
    super.selectFile(path, {pjaxContainerSel: GH_PJAX_CONTAINER_SEL});
  }

  // @override
  loadCodeTree(opts, cb) {
    opts.encodedBranch = encodeURIComponent(decodeURIComponent(opts.repo.branch));
    opts.path = (opts.node && (opts.node.sha || opts.encodedBranch)) || opts.encodedBranch + '?recursive=1';
    this._loadCodeTreeInternal(opts, null, cb);
  }

  get isOnPRPage() {
    const match = window.location.pathname.match(/([^\/]+)\/([^\/]+)(?:\/([^\/]+))?(?:\/([^\/]+))?/);

    if (!match) return false;

    const type = match[3];

    return type === 'pull';
  }

  // @override
  _getTree(path, opts, cb) {
    if (opts.repo.pullNumber) {
      this._getPatch(opts, cb);
    } else {
      this._get(`/git/trees/${path}`, opts, (err, res) => {
        if (err) cb(err);
        else cb(null, res.tree);
      });
    }
  }

  /**
   * Get files that were patched in Pull Request.
   * The diff map that is returned contains changed files, as well as the parents of the changed files.
   * This allows the tree to be filtered for only folders that contain files with diffs.
   * @param {Object} opts: {
   *                  path: the starting path to load the tree,
   *                  repo: the current repository,
   *                  node (optional): the selected node (null to load entire tree),
   *                  token (optional): the personal access token
   *                 }
   * @param {Function} cb(err: error, diffMap: Object)
   */
  _getPatch(opts, cb) {
    const {pullNumber} = opts.repo;

    this._get(`/pulls/${pullNumber}/files?per_page=300`, opts, (err, res) => {
      if (err) cb(err);
      else {
        const diffMap = {};

        res.forEach((file, index) => {
          // Record file patch info
          diffMap[file.filename] = {
            type: 'blob',
            diffId: index,
            action: file.status,
            additions: file.additions,
            blob_url: file.blob_url,
            deletions: file.deletions,
            filename: file.filename,
            path: file.path,
            sha: file.sha
          };

          // Record ancestor folders
          const folderPath = file.filename
            .split('/')
            .slice(0, -1)
            .join('/');
          const split = folderPath.split('/');

          // Aggregate metadata for ancestor folders
          split.reduce((path, curr) => {
            if (path.length) path = `${path}/${curr}`;
            else path = `${curr}`;

            if (diffMap[path] == null) {
              diffMap[path] = {
                type: 'tree',
                filename: path,
                filesChanged: 1,
                additions: file.additions,
                deletions: file.deletions
              };
            } else {
              diffMap[path].additions += file.additions;
              diffMap[path].deletions += file.deletions;
              diffMap[path].filesChanged++;
            }
            return path;
          }, '');
        });

        // Transform to emulate response from get `tree`
        const tree = Object.keys(diffMap).map((fileName) => {
          const patch = diffMap[fileName];
          return {
            patch,
            path: fileName,
            sha: patch.sha,
            type: patch.type,
            url: patch.blob_url
          };
        });

        // Sort by path, needs to be alphabetical order (so parent folders come before children)
        // Note: this is still part of the above transform to mimic the behavior of get tree
        tree.sort((a, b) => a.path.localeCompare(b.path));

        cb(null, tree);
      }
    });
  }

  // @override
  _getSubmodules(tree, opts, cb) {
    const item = tree.filter((item) => /^\.gitmodules$/i.test(item.path))[0];
    if (!item) return cb();

    this._get(`/git/blobs/${item.sha}`, opts, (err, res) => {
      if (err) return cb(err);
      const data = atob(res.content.replace(/\n/g, ''));
      cb(null, parseGitmodules(data));
    });
  }

  _get(path, opts, cb) {
    let url;

    if (path && path.startsWith('http')) {
      url = path;
    } else {
      const host =
        location.protocol + '//' + (location.host === 'github.com' ? 'api.github.com' : location.host + '/api/v3');
      url = `${host}/repos/${opts.repo.username}/${opts.repo.reponame}${path || ''}`;
    }

    const cfg = {url, method: 'GET', cache: false};

    if (opts.token) {
      cfg.headers = {Authorization: 'token ' + opts.token};
    }

    $.ajax(cfg)
      .done((data, textStatus, jqXHR) => {
        if (path && path.indexOf('/git/trees') === 0 && data.truncated) {
          const hugeRepos = this.store.get(STORE.HUGE_REPOS);
          const repo = `${opts.repo.username}/${opts.repo.reponame}`;
          const repos = Object.keys(hugeRepos);
          if (!hugeRepos[repo]) {
            // If there are too many repos memoized, delete the oldest one
            if (repos.length >= GH_MAX_HUGE_REPOS_SIZE) {
              const oldestRepo = repos.reduce((min, p) => (hugeRepos[p] < hugeRepos[min] ? p : min));
              delete hugeRepos[oldestRepo];
            }
            hugeRepos[repo] = new Date().getTime();
            this.store.set(STORE.HUGE_REPOS, hugeRepos);
          }
          this._handleError(cfg, {status: 206}, cb);
        } else cb(null, data, jqXHR);
      })
      .fail((jqXHR) => this._handleError(cfg, jqXHR, cb));
  }
}<commit_msg>Default to master branch on releases and tags pages. Fixes #743. (#811)<commit_after>// When Github page loads at repo path e.g. https://github.com/jquery/jquery, the HTML tree has
//  to contain server-rendered HTML in response of pjax.
// However, that  element doesn't have "id" attribute if the Github page loads at specific
// File e.g. https://github.com/jquery/jquery/blob/master/.editorconfig.
// Therefore, the below selector uses many path but only points to the same  element
const GH_PJAX_CONTAINER_SEL =
  '#js-repo-pjax-container, div[itemtype="http://schema.org/SoftwareSourceCode"] main, [data-pjax-container]';

const GH_CONTAINERS = '.container, .container-lg, .container-responsive';
const GH_HEADER = '.js-header-wrapper > header';
const GH_MAX_HUGE_REPOS_SIZE = 50;
const GH_HIDDEN_RESPONSIVE_CLASS = '.d-none';
const GH_RESPONSIVE_BREAKPOINT = 1010;

class GitHub extends PjaxAdapter {
  constructor(store) {
    super(store);
  }

  // @override
  init($sidebar) {
    const pjaxContainer = $(GH_PJAX_CONTAINER_SEL)[0];
    super.init($sidebar, {pjaxContainer: pjaxContainer});

    // Fix #151 by detecting when page layout is updated.
    // In this case, split-diff page has a wider layout, so need to recompute margin.
    // Note that couldn't do this in response to URL change, since new DOM via pjax might not be ready.
    const diffModeObserver = new window.MutationObserver((mutations) => {
      mutations.forEach((mutation) => {
        if (~mutation.oldValue.indexOf('split-diff') || ~mutation.target.className.indexOf('split-diff')) {
          return $(document).trigger(EVENT.LAYOUT_CHANGE);
        }
      });
    });

    diffModeObserver.observe(document.body, {
      attributes: true,
      attributeFilter: ['class'],
      attributeOldValue: true
    });
  }

  // @override
  getCssClass() {
    return 'octotree-github-sidebar';
  }

  // @override
  canLoadEntireTree(repo) {
    const key = `${repo.username}/${repo.reponame}`;
    const hugeRepos = this.store.get(STORE.HUGE_REPOS);
    if (hugeRepos[key]) {
      // Update the last load time of the repo
      hugeRepos[key] = new Date().getTime();
      this.store.set(STORE.HUGE_REPOS, hugeRepos);
    }
    return !hugeRepos[key];
  }

  // @override
  getCreateTokenUrl() {
    return (
      `${location.protocol}//${location.host}/settings/tokens/new?` +
      'scopes=repo&description=Octotree%20browser%20extension'
    );
  }

  // @override
  updateLayout(sidebarPinned, sidebarVisible, sidebarWidth) {
    const SPACING = 10;
    const $header = $(GH_HEADER);
    const $containers =
      $('html').width() <= GH_RESPONSIVE_BREAKPOINT
        ? $(GH_CONTAINERS).not(GH_HIDDEN_RESPONSIVE_CLASS)
        : $(GH_CONTAINERS);

    const autoMarginLeft = ($(document).width() - $containers.width()) / 2;
    const shouldPushEverything = sidebarPinned && sidebarVisible;
    const smallScreen = autoMarginLeft <= sidebarWidth + SPACING;

    $('html').css('margin-left', shouldPushEverything && smallScreen ? sidebarWidth : '');
    $containers.css('margin-left', shouldPushEverything && smallScreen ? SPACING : '');

    if (shouldPushEverything && !smallScreen) {
      // Override important in Github Header class in large screen
      $header.attr('style', `padding-left: ${sidebarWidth + SPACING}px !important`);
    } else {
      $header.removeAttr('style');
    }
  }

  // @override
  getRepoFromPath(currentRepo, token, cb) {
    if (!octotree.shouldShowOctotree()) {
      return cb();
    }

    // (username)/(reponame)[/(type)][/(typeId)]
    const match = window.location.pathname.match(/([^\/]+)\/([^\/]+)(?:\/([^\/]+))?(?:\/([^\/]+))?/);

    const username = match[1];
    const reponame = match[2];
    const type = match[3];
    const typeId = match[4];

    // Not a repository, skip
    if (~GH_RESERVED_USER_NAMES.indexOf(username) || ~GH_RESERVED_REPO_NAMES.indexOf(reponame)) {
      return cb();
    }

    // Get branch by inspecting URL or DOM, quite fragile so provide multiple fallbacks.
    // TODO would be great if there's a more robust way to do this
    /**
     * Github renders the branch name in one of below structure depending on the length
     * of branch name
     *
     * Option 1: when the length is short enough
     *
     *   feature/1/2/3
     *
     *
     * Option 2: when the length is too long
     *
     *   feature/1/2/3...
     *
     */
    const branchDropdownMenuSummary = $('.branch-select-menu summary');
    const branchNameInTitle = branchDropdownMenuSummary.attr('title');
    const branchNameInSpan = branchDropdownMenuSummary.find('span').text();
    const branchFromSummary =
      branchNameInTitle && branchNameInTitle.toLowerCase().startsWith('switch branches')
        ? branchNameInSpan
        : branchNameInTitle;

    const branch =
      // Pick the commit ID as branch name when the code page is listing tree in a particular commit
      (type === 'commit' && typeId) ||
      // Pick 'master' as branch name when viewing repo's releases or tags
      ((type === 'releases' || type === 'tags') && 'master') ||
      // Pick the commit ID or branch name from the DOM
      branchFromSummary ||
      ($('.overall-summary .numbers-summary .commits a').attr('href') || '').replace(
        `/${username}/${reponame}/commits/`,
        ''
      ) ||
      // Pull requests page
      ($('.commit-ref.base-ref').attr('title') || ':').match(/:(.*)/)[1] ||
      // Reuse last selected branch if exist
      (currentRepo.username === username && currentRepo.reponame === reponame && currentRepo.branch) ||
      // Get default branch from cache
      this._defaultBranch[username + '/' + reponame];

    const isPR = type === 'pull';
    const showOnlyChangedInPR = this.store.get(STORE.PR);
    const pullNumber = isPR && showOnlyChangedInPR ? typeId : null;
    const repo = {username, reponame, branch, pullNumber};
    if (repo.branch) {
      cb(null, repo);
    } else {
      // Still no luck, get default branch for real
      this._get(null, {repo, token}, (err, data) => {
        if (err) return cb(err);
        repo.branch = this._defaultBranch[username + '/' + reponame] = data.default_branch || 'master';
        cb(null, repo);
      });
    }
  }

  // @override
  selectFile(path) {
    super.selectFile(path, {pjaxContainerSel: GH_PJAX_CONTAINER_SEL});
  }

  // @override
  loadCodeTree(opts, cb) {
    opts.encodedBranch = encodeURIComponent(decodeURIComponent(opts.repo.branch));
    opts.path = (opts.node && (opts.node.sha || opts.encodedBranch)) || opts.encodedBranch + '?recursive=1';
    this._loadCodeTreeInternal(opts, null, cb);
  }

  get isOnPRPage() {
    const match = window.location.pathname.match(/([^\/]+)\/([^\/]+)(?:\/([^\/]+))?(?:\/([^\/]+))?/);

    if (!match) return false;

    const type = match[3];

    return type === 'pull';
  }

  // @override
  _getTree(path, opts, cb) {
    if (opts.repo.pullNumber) {
      this._getPatch(opts, cb);
    } else {
      this._get(`/git/trees/${path}`, opts, (err, res) => {
        if (err) cb(err);
        else cb(null, res.tree);
      });
    }
  }

  /**
   * Get files that were patched in Pull Request.
   * The diff map that is returned contains changed files, as well as the parents of the changed files.
   * This allows the tree to be filtered for only folders that contain files with diffs.
   * @param {Object} opts: {
   *                  path: the starting path to load the tree,
   *                  repo: the current repository,
   *                  node (optional): the selected node (null to load entire tree),
   *                  token (optional): the personal access token
   *                 }
   * @param {Function} cb(err: error, diffMap: Object)
   */
  _getPatch(opts, cb) {
    const {pullNumber} = opts.repo;

    this._get(`/pulls/${pullNumber}/files?per_page=300`, opts, (err, res) => {
      if (err) cb(err);
      else {
        const diffMap = {};

        res.forEach((file, index) => {
          // Record file patch info
          diffMap[file.filename] = {
            type: 'blob',
            diffId: index,
            action: file.status,
            additions: file.additions,
            blob_url: file.blob_url,
            deletions: file.deletions,
            filename: file.filename,
            path: file.path,
            sha: file.sha
          };

          // Record ancestor folders
          const folderPath = file.filename
            .split('/')
            .slice(0, -1)
            .join('/');
          const split = folderPath.split('/');

          // Aggregate metadata for ancestor folders
          split.reduce((path, curr) => {
            if (path.length) path = `${path}/${curr}`;
            else path = `${curr}`;

            if (diffMap[path] == null) {
              diffMap[path] = {
                type: 'tree',
                filename: path,
                filesChanged: 1,
                additions: file.additions,
                deletions: file.deletions
              };
            } else {
              diffMap[path].additions += file.additions;
              diffMap[path].deletions += file.deletions;
              diffMap[path].filesChanged++;
            }
            return path;
          }, '');
        });

        // Transform to emulate response from get `tree`
        const tree = Object.keys(diffMap).map((fileName) => {
          const patch = diffMap[fileName];
          return {
            patch,
            path: fileName,
            sha: patch.sha,
            type: patch.type,
            url: patch.blob_url
          };
        });

        // Sort by path, needs to be alphabetical order (so parent folders come before children)
        // Note: this is still part of the above transform to mimic the behavior of get tree
        tree.sort((a, b) => a.path.localeCompare(b.path));

        cb(null, tree);
      }
    });
  }

  // @override
  _getSubmodules(tree, opts, cb) {
    const item = tree.filter((item) => /^\.gitmodules$/i.test(item.path))[0];
    if (!item) return cb();

    this._get(`/git/blobs/${item.sha}`, opts, (err, res) => {
      if (err) return cb(err);
      const data = atob(res.content.replace(/\n/g, ''));
      cb(null, parseGitmodules(data));
    });
  }

  _get(path, opts, cb) {
    let url;

    if (path && path.startsWith('http')) {
      url = path;
    } else {
      const host =
        location.protocol + '//' + (location.host === 'github.com' ? 'api.github.com' : location.host + '/api/v3');
      url = `${host}/repos/${opts.repo.username}/${opts.repo.reponame}${path || ''}`;
    }

    const cfg = {url, method: 'GET', cache: false};

    if (opts.token) {
      cfg.headers = {Authorization: 'token ' + opts.token};
    }

    $.ajax(cfg)
      .done((data, textStatus, jqXHR) => {
        if (path && path.indexOf('/git/trees') === 0 && data.truncated) {
          const hugeRepos = this.store.get(STORE.HUGE_REPOS);
          const repo = `${opts.repo.username}/${opts.repo.reponame}`;
          const repos = Object.keys(hugeRepos);
          if (!hugeRepos[repo]) {
            // If there are too many repos memoized, delete the oldest one
            if (repos.length >= GH_MAX_HUGE_REPOS_SIZE) {
              const oldestRepo = repos.reduce((min, p) => (hugeRepos[p] < hugeRepos[min] ? p : min));
              delete hugeRepos[oldestRepo];
            }
            hugeRepos[repo] = new Date().getTime();
            this.store.set(STORE.HUGE_REPOS, hugeRepos);
          }
          this._handleError(cfg, {status: 206}, cb);
        } else cb(null, data, jqXHR);
      })
      .fail((jqXHR) => this._handleError(cfg, jqXHR, cb));
  }
}<|endoftext|>


<commit_before>var alloc_http_request = new Array();

function makeAjaxRequest(url,entityid) {
  $("#"+entityid).html('');
  jQuery.get(url,'',function(data) {
    $("#"+entityid).hide();
    $("#"+entityid).html(data);
    $("#"+entityid).fadeIn("fast");
  })
}

function set_grow_shrink_box(id, images, text, id_to_hide) {
  if ($("#"+id).is(':visible')) {
    image = images+'small_grow.gif';
  } else {
    image = images+'small_shrink.gif';
  }
  // hide or show the actual div
  $("#"+id).slideToggle("fast");

  // toggle the other div - if any
  if (id_to_hide) {
    $("#"+id_to_hide).slideToggle("fast");
  }
  str = "<nobr>"+text+"</nobr>"
  $('#button_'+id).html(str);
  return false;
}

// This is a generic show/hide for anything
function set_grow_shrink(id, id_to_hide, use_classes_instead_of_ids) {
  // toggle the other div - if any
  if (use_classes_instead_of_ids && id_to_hide) {
    $("."+id_to_hide).slideToggle("fast");
  } else if (id_to_hide) {
    $("#"+id_to_hide).slideToggle("fast");
  }
  // hide or show the actual div
  if (use_classes_instead_of_ids) {
    $("."+id).slideToggle("fast");
  } else {
    $("#"+id).slideToggle("fast");
  }
  return false;
}

function sidebyside_activate(id,arr) {
  if (id == "sbsAll") {
    for (var i=0; i<arr.length; i++) {
      if (arr[i] != "sbsAll") {
        $("#"+arr[i]).show();
        $('#sbs_link_'+arr[i]).removeClass("sidebyside_active").addClass("sidebyside");
      }
    }
    $('#sbs_link_' + id).addClass("sidebyside_active");

  } else {
    for (var i=0; i<arr.length; i++) {
      if (arr[i] != "sbsAll") {
        $("#"+arr[i]).hide();
      }
      $('#sbs_link_' + arr[i]).removeClass("sidebyside_active").addClass("sidebyside");
    }
    $('#sbs_link_' + id).addClass("sidebyside_active");
    $("#"+id).show();
  }
}

// These global variables are for the setTimeout() below
var alloc_current_resizable_textarea = "";
var alloc_current_resizable_textarea_default_height = "";
var alloc_current_resizable_textarea_timer = "";

// this function dynamically resizes a text area as data is inputted
function adjust_textarea(textarea, default_height) {
  // a div is setup off screen, we use that div to determine the height of the textarea
  alloc_current_resizable_textarea = textarea;
  alloc_current_resizable_textarea_default_height = default_height;
  var shadow = document.getElementById("shadow_" + textarea.id);
  shadow.style.width=parseInt(textarea.clientWidth-8)+'px';
  shadow.innerHTML = textarea.value.replace(/[\n]/g,'
 ');
  var shadow_height = shadow.clientHeight;
  if(shadow_height < default_height) {
    var n = default_height;
  } else {
    var n = shadow_height+14;
  }
  textarea.style.height = n+'px';
  alloc_current_resizable_textarea_timer = setTimeout('adjust_textarea(alloc_current_resizable_textarea,alloc_current_resizable_textarea_default_height)', 1000);
}

function stop_textarea_timer() {
  clearTimeout(alloc_current_resizable_textarea_timer);
}

function help_text_on(id, str) {
  $('#main').append("

");
  $('#helper').hide().html(str).corner();

  offset = $('#'+id).offset();

  x = offset.left -400;
  if (x < 0) {
    x = x + 380;
  }
  $("#helper").css('left',x);

  y = offset.top - 50;
  if (y > 350) {
    y = y-$('#helper').height() -40;
  }

  $("#helper").css('top',y);
  $("#helper").fadeIn("normal");
}
function help_text_off(id) {
  $("#helper").fadeOut("normal");
  $('#helper').remove();
}

<commit_msg>12541 Fixed konqueror bug where the Client and Project dynamic tabs completely don't work.<commit_after>var alloc_http_request = new Array();

function makeAjaxRequest(url,entityid) {
  $("#"+entityid).html('');
  jQuery.get(url,'',function(data) {
    $("#"+entityid).hide();
    $("#"+entityid).html(data);
    $("#"+entityid).fadeIn("fast");
  })
}

function set_grow_shrink_box(id, images, text, id_to_hide) {
  if ($("#"+id).is(':visible')) {
    image = images+'small_grow.gif';
  } else {
    image = images+'small_shrink.gif';
  }
  // hide or show the actual div
  $("#"+id).slideToggle("fast");

  // toggle the other div - if any
  if (id_to_hide) {
    $("#"+id_to_hide).slideToggle("fast");
  }
  str = "<nobr>"+text+"</nobr>"
  $('#button_'+id).html(str);
  return false;
}

// This is a generic show/hide for anything
function set_grow_shrink(id, id_to_hide, use_classes_instead_of_ids) {
  // toggle the other div - if any
  if (use_classes_instead_of_ids && id_to_hide) {
    $("."+id_to_hide).slideToggle("fast");
  } else if (id_to_hide) {
    $("#"+id_to_hide).slideToggle("fast");
  }
  // hide or show the actual div
  if (use_classes_instead_of_ids) {
    $("."+id).slideToggle("fast");
  } else {
    $("#"+id).slideToggle("fast");
  }
  return false;
}

function sidebyside_activate(id,arr) {
  if (id == "sbsAll") {
    for (var i=0; i<arr.length; i++) {
      if (arr[i] != "sbsAll") {
        //$("#"+arr[i]).show(); konqueror doesn't like this
        document.getElementById(arr[i]).style.display = 'inline';
        $('#sbs_link_'+arr[i]).removeClass("sidebyside_active").addClass("sidebyside");
      }
    }
    $('#sbs_link_' + id).addClass("sidebyside_active");

  } else {
    for (var i=0; i<arr.length; i++) {
      if (arr[i] != "sbsAll") {
        //$("#"+arr[i]).hide();  konqueror doesn't like this
        document.getElementById(arr[i]).style.display = 'none';
      }
      $('#sbs_link_' + arr[i]).removeClass("sidebyside_active").addClass("sidebyside");
    }
    $('#sbs_link_' + id).addClass("sidebyside_active");
    //$("#"+id).show(); konqueror doesn't like this
    document.getElementById(id).style.display = 'inline';
  }
}

// These global variables are for the setTimeout() below
var alloc_current_resizable_textarea = "";
var alloc_current_resizable_textarea_default_height = "";
var alloc_current_resizable_textarea_timer = "";

// this function dynamically resizes a text area as data is inputted
function adjust_textarea(textarea, default_height) {
  // a div is setup off screen, we use that div to determine the height of the textarea
  alloc_current_resizable_textarea = textarea;
  alloc_current_resizable_textarea_default_height = default_height;
  var shadow = document.getElementById("shadow_" + textarea.id);
  shadow.style.width=parseInt(textarea.clientWidth-8)+'px';
  shadow.innerHTML = textarea.value.replace(/[\n]/g,'
 ');
  var shadow_height = shadow.clientHeight;
  if(shadow_height < default_height) {
    var n = default_height;
  } else {
    var n = shadow_height+14;
  }
  textarea.style.height = n+'px';
  alloc_current_resizable_textarea_timer = setTimeout('adjust_textarea(alloc_current_resizable_textarea,alloc_current_resizable_textarea_default_height)', 1000);
}

function stop_textarea_timer() {
  clearTimeout(alloc_current_resizable_textarea_timer);
}

function help_text_on(id, str) {
  $('#main').append("

");
  $('#helper').hide().html(str).corner();

  offset = $('#'+id).offset();

  x = offset.left -400;
  if (x < 0) {
    x = x + 380;
  }
  $("#helper").css('left',x);

  y = offset.top - 50;
  if (y > 350) {
    y = y-$('#helper').height() -40;
  }

  $("#helper").css('top',y);
  $("#helper").fadeIn("normal");
}
function help_text_off(id) {
  $("#helper").fadeOut("normal");
  $('#helper').remove();
}

<|endoftext|>


<commit_before>
var unfollow = require('./unfollow.js');

unfollow();
<commit_msg>removed derp<commit_after><|endoftext|>