Add code paths to console_clean/console_boot so that applications can be selectively loaded for debugging purposes

#!/bin/sh

set -e

# Path to this script
SCRIPT=$(readlink $0 || true)
if [ -z $SCRIPT ]; then
    SCRIPT=$0
fi;
# Parent directory of this script
SCRIPT_DIR="$(cd `dirname "$SCRIPT"` && pwd -P)"
# Root directory of all releases
RELEASE_ROOT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd -P)"
# Name of the release
REL_NAME="<%= release_name %>"
# Current version of the release
REL_VSN="<%= release_version %>"
# Current version of ERTS being used
# If this is not present/unset, it will be detected
<%= unless is_nil(erts_vsn) do %>ERTS_VSN="<%= erts_vsn %>"<% end %>
# VM code loading mode, embedded by default, can also be interactive
# See http://erlang.org/doc/man/code.html
CODE_LOADING_MODE="${CODE_LOADING_MODE:-embedded}"
# Path to start_erl.data
START_ERL_DATA="$RELEASE_ROOT_DIR/releases/start_erl.data"
# Directory containing the current version of this release
REL_DIR="$RELEASE_ROOT_DIR/releases/$REL_VSN"
# The lib directory for this release
REL_LIB_DIR="$RELEASE_ROOT_DIR/lib"
# Options passed to erl
ERL_OPTS="<%= release.profile.erl_opts %>"
# When stdout is piped to a file, this is the directory those files will
# be stored in. defaults to /log in the release root directory
RUNNER_LOG_DIR="${RUNNER_LOG_DIR:-$RELEASE_ROOT_DIR/log}"
# A string of extra options to pass to erl, here for plugins
EXTRA_OPTS=""

# Pre-start/stop event hook paths
PRE_START_HOOK="$REL_DIR/hooks/pre_start"
POST_START_HOOK="$REL_DIR/hooks/post_start"
PRE_STOP_HOOK="$REL_DIR/hooks/pre_stop"
POST_STOP_HOOK="$REL_DIR/hooks/post_stop"

# Get node pid
get_pid() {
    if output="$(nodetool rpcterms os getpid)"
    then
        echo "$output" | sed -e 's/"//g'
        return 0
    else
        echo "$output"
        return 1
    fi
}

# Generate a unique nodename
gen_nodename() {
    id="longname$(gen_id)-${NAME}"
    "$BINDIR/erl" -boot start_clean -eval '[Host] = tl(string:tokens(atom_to_list(node()),"@")), io:format("~s~n", [Host]), halt()' -noshell ${NAME_TYPE} $id
}

# Generate a random id
gen_id() {
    od -t x -N 4 /dev/urandom | head -n1 | awk '{print $2}'
}

# Control a node
# Use like `nodetool "ping"`
nodetool() {
    command="$1"; shift

    "$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" "$NAME_TYPE" "$NAME" \
                            -setcookie "$COOKIE" "$command" $@
}

# Run an escript in the node's environment
# Use like `escript "path/to/escript"`
escript() {
    shift; scriptpath="$1"; shift
    export RELEASE_ROOT_DIR

    "$ERTS_DIR/bin/escript" "$ROOTDIR/$scriptpath" $@
}

# Private. For determining the version of ERTS available to the release
_detect_erts_vsn() {
    erl -boot start_clean -eval 'Ver = erlang:system_info(version), io:format("~s~n", [Ver]), halt()' -noshell
}

# Private. Gets a list of code paths for this release
_get_code_paths() {
    erl -noshell -boot start_clean -eval "{ok, [{release,_,_,Apps}]} = file:consult(\"$REL_DIR/$REL_NAME.rel\"),lists:foreach(fun(A) -> io:fwrite(\"-pa $ROOTDIR/lib/~p-~s/ebin \", [element(1, A), element(2, A)]) end, Apps),halt()."
}

# Private. For setting ERTS_DIR and ROOTDIR
_find_erts_dir() {
    __erts_dir="$RELEASE_ROOT_DIR/erts-$ERTS_VSN"
    if [ -d "$__erts_dir" ]; then
        ERTS_DIR="$__erts_dir";
        ROOTDIR="$RELEASE_ROOT_DIR"
    else
        __erl="$(which erl)"
        code="io:format(\"~s\", [code:root_dir()]), halt()."
        __erl_root="$("$__erl" -noshell -eval "$code")"
        ERTS_DIR="$__erl_root/erts-$ERTS_VSN"
        ROOTDIR="$__erl_root"
    fi
}

# Private. Open a shell on a remote node
_rem_sh() {
    # Generate a unique id used to allow multiple remsh to the same node
    # transparently
    id="remsh$(gen_id)-${NAME}"

    # Get the node's ticktime so that we use the same thing.
    TICKTIME="$(nodetool rpcterms net_kernel get_net_ticktime)"

    # Setup remote shell command to control node
    if [ ! -z "$USE_ERL_SHELL" ]; then
        exec "$BINDIR/erl" \
            -hidden \
            -boot start_clean -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -kernel net_ticktime $TICKTIME \
            "$NAME_TYPE" "$id" -remsh "$NAME" -setcookie "$COOKIE"
    else
        __code_paths=$(_get_code_paths)
        exec "$BINDIR/erl" \
            -pa "$CONSOLIDATED_DIR" \
            ${__code_paths} \
            -hidden -noshell \
            -boot start_clean -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -kernel net_ticktime $TICKTIME \
            -user Elixir.IEx.CLI "$NAME_TYPE" "$id" -setcookie "$COOKIE" \
            -extra --no-halt +iex -"$NAME_TYPE" "$id" --cookie "$COOKIE" --remsh "$NAME"
    fi
}

# Output a start command for the last argument of run_erl
_start_command() {
    printf "exec \"%s\" \"%s\" -- %s %s" "$RELEASE_ROOT_DIR/bin/$REL_NAME" \
           "$START_OPTION" "${ARGS}" "${EXTRA_OPTS}"
}

# If ERTS_VSN is not set, detect it
if [ -z "$ERTS_VSN" ]; then
    ERTS_VSN="$(_detect_erts_vsn)"
    echo "$ERTS_VSN $REL_VSN" > "$START_ERL_DATA"
fi

# Allow override of where to look for config files
# By default it's $CWD/
if [ -z "$RELEASE_CONFIG_DIR" ]; then
    RELEASE_CONFIG_DIR="$RELEASE_ROOT_DIR"
fi

# Set VMARGS_PATH, the path to the vm.args file to use
# Use $RELEASE_CONFIG_DIR/vm.args if exists, otherwise releases/VSN/vm.args
if [ -z "$VMARGS_PATH" ]; then
    if [ -f "$RELEASE_CONFIG_DIR/vm.args" ]; then
        VMARGS_PATH="$RELEASE_CONFIG_DIR/vm.args"
    else
        VMARGS_PATH="$REL_DIR/vm.args"
    fi
fi

orig_vmargs_path="$VMARGS_PATH.orig"
if [ $REPLACE_OS_VARS ]; then
    #Make sure we don't break dev mode by keeping the symbolic link to
    #the user's vm.args
    if [ ! -L "$orig_vmargs_path" ]; then
       #we're in copy mode, rename the vm.args file to vm.args.orig
       mv "$VMARGS_PATH" "$orig_vmargs_path"
    fi

    awk '{while(match($0,"[$]{[^}]*}")) {var=substr($0,RSTART+2,RLENGTH -3);gsub("[$]{"var"}",ENVIRON[var])}}1' < "$orig_vmargs_path" > "$VMARGS_PATH"
 else
    #We don't need to replace env. vars, just rename the
    #symlink vm.args.orig to vm.args, and keep it as a
    #symlink.
    if [ -L "$orig_vmargs_path" ]; then
       mv "$orig_vmargs_path" "$VMARGS_PATH"
    fi
fi

# Make sure log directory exists
mkdir -p "$RUNNER_LOG_DIR"

# Set SYS_CONFIG_PATH, the path to the sys.config file to use
# Use $RELEASE_CONFIG_DIR/sys.config if exists, otherwise releases/VSN/sys.config
if [ -z "$SYS_CONFIG_PATH" ]; then
    if [ -f "$RELEASE_CONFIG_DIR/sys.config" ]; then
        SYS_CONFIG_PATH="$RELEASE_CONFIG_DIR/sys.config"
    else
        SYS_CONFIG_PATH="$REL_DIR/sys.config"
    fi
fi

orig_sys_config_path="$SYS_CONFIG_PATH.orig"
if [ $REPLACE_OS_VARS ]; then
    #Make sure we don't break dev mode by keeping the symbolic link to
    #the user's sys.config
    if [ ! -L "$orig_sys_config_path" ]; then
       #We're in copy mode, rename sys.config to sys.config.orig
       mv "$SYS_CONFIG_PATH" "$orig_sys_config_path"
    fi

    awk '{while(match($0,"[$]{[^}]*}")) {var=substr($0,RSTART+2,RLENGTH -3);gsub("[$]{"var"}",ENVIRON[var])}}1' < "$orig_sys_config_path" > "$SYS_CONFIG_PATH"
 else
    #We don't need to replace env. vars, just rename the
    #symlink sys.config.orig to sys.config. Keep it as
    #a symlink.
    if [ -L "$orig_sys_config_path" ]; then
       mv "$orig_sys_config_path"  "$SYS_CONFIG_PATH"
    fi
fi

# Extract the target node name from node.args
# Should be `-sname somename` or `-name somename@somehost`
NAME_ARG=$(egrep '^-s?name' "$VMARGS_PATH" || true)
if [ -z "$NAME_ARG" ]; then
    echo "vm.args needs to have either -name or -sname parameter."
    exit 1
fi

# Extract the name type and name from the NAME_ARG for REMSH
# NAME_TYPE should be -name or -sname
NAME_TYPE="$(echo "$NAME_ARG" | awk '{print $1}')"
# NAME will be either `somename` or `somename@somehost`
NAME="$(echo "$NAME_ARG" | awk '{print $2}')"

# Where the pipe will be stored when using `start`
# This is used so you can attach the running application to the current
# shell using `attach`
PIPE_DIR="${PIPE_DIR:-$RELEASE_ROOT_DIR/tmp/erl_pipes/$NAME/}"

# Extract the target cookie
COOKIE_ARG="$(grep '^-setcookie' "$VMARGS_PATH" || true)"
DEFAULT_COOKIE_FILE="$HOME/.erlang.cookie"
if [ -z "$COOKIE_ARG" ]; then
    if [ -f "$DEFAULT_COOKIE_FILE" ]; then
        COOKIE="$(cat "$DEFAULT_COOKIE_FILE")"
    else
        printf "a secret cookie must be provided in one of the following ways:\n  - with vm.args using the -setcookie parameter,\n  or\n  by writing the cookie to '$DEFAULT_COOKIE_FILE', with permissions set to 0400"
        exit 1
    fi
else
    # Extract cookie name from COOKIE_ARG
    COOKIE="$(echo "$COOKIE_ARG" | awk '{print $2}')"
fi

_find_erts_dir
export ROOTDIR="$RELEASE_ROOT_DIR"
export BINDIR="$ERTS_DIR/bin"
export EMU="beam"
export PROGNAME="erl"
export LD_LIBRARY_PATH="$ERTS_DIR/lib:$LD_LIBRARY_PATH"
ERTS_LIB_DIR="$ERTS_DIR/../lib"
CONSOLIDATED_DIR="$ROOTDIR/lib/${REL_NAME}-${REL_VSN}/consolidated"

cd "$ROOTDIR"

# User can specify an sname without @hostname
# This will fail when creating remote shell
# So here we check for @ and add @hostname if missing
case $NAME in
    *@*)
        # Nothing to do
        ;;
    *)
        NAME=$NAME@$(gen_nodename)
        ;;
esac

# Check the first argument for instructions
case "$1" in
    start|start_boot)

        # Make sure there is not already a node running
        #RES=`$NODETOOL ping`
        #if [ "$RES" = "pong" ]; then
        #    echo "Node is already running!"
        #    exit 1
        #fi
        # Save this for later.
        CMD=$1
        case "$1" in
            start)
                shift
                START_OPTION="console"
                HEART_OPTION="start"
                ;;
            start_boot)
                shift
                START_OPTION="console_boot"
                HEART_OPTION="start_boot"
                ;;
        esac
        ARGS="$@"
        RUN_PARAM="$@"

        [ -f "$PRE_START_HOOK" ] && . "$PRE_START_HOOK"

        # Set arguments for the heart command
        set -- "$SCRIPT_DIR/$REL_NAME" "$HEART_OPTION"
        [ "$RUN_PARAM" ] && set -- "$@" "$RUN_PARAM"

        # Export the HEART_COMMAND
        HEART_COMMAND="$RELEASE_ROOT_DIR/bin/$REL_NAME $CMD"
        export HEART_COMMAND

        mkdir -p "$PIPE_DIR"

        "$BINDIR/run_erl" -daemon "$PIPE_DIR" "$RUNNER_LOG_DIR" \
                          "$(_start_command)"

        [ -f "$POST_START_HOOK" ] && . "$POST_START_HOOK"
        ;;

    stop)
        [ -f "$PRE_STOP_HOOK" ] && . "$PRE_STOP_HOOK"
        # Wait for the node to completely stop...
        PID="$(get_pid)"
        if ! nodetool "stop"; then
            exit 1
        fi
        while $(kill -s 0 "$PID" 2>/dev/null);
        do
            sleep 1
        done
        [ -f "$POST_STOP_HOOK" ] && . "$POST_STOP_HOOK"
        ;;

    restart)
        [ -f "$PRE_START_HOOK" ] && . "$PRE_START_HOOK"
        ## Restart the VM without exiting the process
        if ! nodetool "restart"; then
            exit 1
        fi
        ;;

    reboot)
        [ -f "$PRE_START_HOOK" ] && . "$PRE_START_HOOK"
        ## Restart the VM completely (uses heart to restart it)
        if ! nodetool "reboot"; then
            exit 1
        fi
        ;;

    pid)
        ## Get the VM's pid
        if ! get_pid; then
            exit 1
        fi
        ;;

    ping)
        ## See if the VM is alive
        if ! nodetool "ping"; then
            exit 1
        fi
        ;;

    escript)
        ## Run an escript under the node's environment
        if ! escript $@; then
            exit 1
        fi
        ;;

    attach)
        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift
        exec "$BINDIR/to_erl" "$PIPE_DIR"
        ;;

    remote_console)
        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift
        _rem_sh
        ;;

    upgrade|downgrade|install)
        if [ -z "$2" ]; then
            echo "Missing package argument"
            echo "Usage: $REL_NAME $1 {package base name}"
            echo "NOTE {package base name} MUST NOT include the .tar.gz suffix"
            exit 1
        fi

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        exec "$BINDIR/escript" "$ROOTDIR/bin/install_upgrade.escript" \
             "install" "$REL_NAME" "$NAME_TYPE" "$NAME" "$COOKIE" "$2"
        ;;

    unpack)
        if [ -z "$2" ]; then
            echo "Missing package argument"
            echo "Usage: $REL_NAME $1 {package base name}"
            echo "NOTE {package base name} MUST NOT include the .tar.gz suffix"
            exit 1
        fi

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        exec "$BINDIR/escript" "$ROOTDIR/bin/install_upgrade.escript" \
             "unpack" "$REL_NAME" "$NAME_TYPE" "$NAME" "$COOKIE" "$2"
        ;;

    console|console_clean|console_boot)
        # .boot file typically just $REL_NAME (ie, the app name)
        # however, for debugging, sometimes start_clean.boot is useful.
        # For e.g. 'setup', one may even want to name another boot script.
        case "$1" in
            console)
                if [ -f "$REL_DIR/$REL_NAME.boot" ]; then
                  BOOTFILE="$REL_DIR/$REL_NAME"
                else
                  BOOTFILE="$REL_DIR/start"
                fi
                ;;
            console_clean)
                BOOTFILE="$ROOTDIR/bin/start_clean"
                ;;
            console_boot)
                shift
                BOOTFILE="$1"
                shift
                ;;
        esac
        # Setup beam-required vars
        EMU="beam"
        PROGNAME="${0#*/}"

        export EMU
        export PROGNAME

        # Store passed arguments since they will be erased by `set`
        ARGS="$@"

        # Start the VM, executing pre_start hook along
        # the way. We can't run the post_start hook because
        # the console will crash with no TTY attached
        [ -f "$PRE_START_HOOK" ] && . "$PRE_START_HOOK"

        __code_paths=$(_get_code_paths)
        # Build an array of arguments to pass to exec later on
        # Build it here because this command will be used for logging.
        set -- "$BINDIR/erlexec" \
            -boot "$BOOTFILE" \
            -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -env ERL_LIBS "$REL_LIB_DIR" \
            -pa "$CONSOLIDATED_DIR" \
            ${__code_paths} \
            -args_file "$VMARGS_PATH" \
            -config "$SYS_CONFIG_PATH" \
            -mode "$CODE_LOADING_MODE" \
            ${ERL_OPTS} \
            -user Elixir.IEx.CLI \
            -extra --no-halt +iex

        # Dump environment info for logging purposes
        echo "Exec: $@" -- ${1+$ARGS} ${EXTRA_OPTS}
        echo "Root: $ROOTDIR"

        # Log the startup
        echo "$RELEASE_ROOT_DIR"
        logger -t "$REL_NAME[$$]" "Starting up"

        exec "$@" -- ${1+$ARGS} ${EXTRA_OPTS}
        ;;

    foreground)
        # start up the release in the foreground for use by runit
        # or other supervision services

        [ -f "$REL_DIR/$REL_NAME.boot" ] && BOOTFILE="$REL_NAME" || BOOTFILE=start
        FOREGROUNDOPTIONS="-noshell -noinput +Bd"

        # Setup beam-required vars
        EMU=beam
        PROGNAME="${0#*/}"

        export EMU
        export PROGNAME

        # Store passed arguments since they will be erased by `set`
        ARGS="$@"

        # Start the VM, executing pre and post start hooks
        [ -f "$PRE_START_HOOK" ] && . "$PRE_START_HOOK"

        # Build an array of arguments to pass to exec later on
        # Build it here because this command will be used for logging.
        set -- "$BINDIR/erlexec" $FOREGROUNDOPTIONS \
            -boot "$REL_DIR/$BOOTFILE" -mode "$CODE_LOADING_MODE" -config "$SYS_CONFIG_PATH" \
            -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -args_file "$VMARGS_PATH" \
            -env ERL_LIBS "$REL_LIB_DIR" \
            -pa "$CONSOLIDATED_DIR" \
            ${ERL_OPTS} \
            -extra ${EXTRA_OPTS}

        # Dump environment info for logging purposes
        echo "Exec: $@" -- ${1+$ARGS}
        echo "Root: $ROOTDIR"

        trap '{}' QUIT TERM KILL HUP SIGUSR1 SIGUSR2
        "$@" -- ${1+$ARGS} &
        __bg_pid=$!
        [ -f "$POST_START_HOOK" ] && . "$POST_START_HOOK"
        wait $__bg_pid
        ;;
    rpc)
        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift

        nodetool rpc $@
        ;;
    rpcterms)
        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift

        nodetool rpcterms $@
        ;;
    eval)
        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift
        nodetool "eval" $@
        ;;
    command)
        # Execute as command-line utility
        #
        # Like the escript command, this does not start the OTP application.
        # If your command depends on a running OTP application,
        # use
        #
        #     {:ok, _} = Application.ensure_all_started(:your_app)

        shift
        MODULE="$1"; shift
        FUNCTION="$1"; shift

        # Save extra arguments
        ARGS="$@"

        # Build arguments for erlexec
        set -- "$ERL_OPTS"
        [ "$SYS_CONFIG_PATH" ] && set -- "$@" -config "$SYS_CONFIG_PATH"
        set -- "$@" -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR"
        set -- "$@" -noshell
        set -- "$@" -boot start_clean
        set -- "$@" -s "$MODULE" "$FUNCTION"

        $BINDIR/erlexec $@ -extra $ARGS
        exit "$?"
        ;;
    *)
        __command_path="$REL_DIR/commands/$1"
        if [ -f "$__command_path" ]; then
            . "$__command_path"
        else
            echo "Usage: $REL_NAME {start|start_boot <file>|foreground|stop|restart|reboot|pid|ping|console|console_clean|console_boot <file>|attach|remote_console|upgrade|downgrade|install|escript|rpc|rpcterms|eval|command <module> <function> <args>}"
            exit 1
        fi
        ;;
esac

exit 0

#!/bin/sh

set -e

# Path to this script
SCRIPT=$(readlink $0 || true)
if [ -z $SCRIPT ]; then
    SCRIPT=$0
fi;
# Parent directory of this script
SCRIPT_DIR="$(cd `dirname "$SCRIPT"` && pwd -P)"
# Root directory of all releases
RELEASE_ROOT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd -P)"
# Name of the release
REL_NAME="<%= release_name %>"
# Current version of the release
REL_VSN="<%= release_version %>"
# Current version of ERTS being used
# If this is not present/unset, it will be detected
<%= unless is_nil(erts_vsn) do %>ERTS_VSN="<%= erts_vsn %>"<% end %>
# VM code loading mode, embedded by default, can also be interactive
# See http://erlang.org/doc/man/code.html
CODE_LOADING_MODE="${CODE_LOADING_MODE:-embedded}"
# Path to start_erl.data
START_ERL_DATA="$RELEASE_ROOT_DIR/releases/start_erl.data"
# Directory containing the current version of this release
REL_DIR="$RELEASE_ROOT_DIR/releases/$REL_VSN"
# The lib directory for this release
REL_LIB_DIR="$RELEASE_ROOT_DIR/lib"
# Options passed to erl
ERL_OPTS="<%= release.profile.erl_opts %>"
# When stdout is piped to a file, this is the directory those files will
# be stored in. defaults to /log in the release root directory
RUNNER_LOG_DIR="${RUNNER_LOG_DIR:-$RELEASE_ROOT_DIR/log}"
# A string of extra options to pass to erl, here for plugins
EXTRA_OPTS=""

# Pre-start/stop event hook paths
PRE_START_HOOK="$REL_DIR/hooks/pre_start"
POST_START_HOOK="$REL_DIR/hooks/post_start"
PRE_STOP_HOOK="$REL_DIR/hooks/pre_stop"
POST_STOP_HOOK="$REL_DIR/hooks/post_stop"

# Get node pid
get_pid() {
    if output="$(nodetool rpcterms os getpid)"
    then
        echo "$output" | sed -e 's/"//g'
        return 0
    else
        echo "$output"
        return 1
    fi
}

# Generate a unique nodename
gen_nodename() {
    id="longname$(gen_id)-${NAME}"
    "$BINDIR/erl" -boot start_clean -eval '[Host] = tl(string:tokens(atom_to_list(node()),"@")), io:format("~s~n", [Host]), halt()' -noshell ${NAME_TYPE} $id
}

# Generate a random id
gen_id() {
    od -t x -N 4 /dev/urandom | head -n1 | awk '{print $2}'
}

# Control a node
# Use like `nodetool "ping"`
nodetool() {
    command="$1"; shift

    "$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" "$NAME_TYPE" "$NAME" \
                            -setcookie "$COOKIE" "$command" $@
}

# Run an escript in the node's environment
# Use like `escript "path/to/escript"`
escript() {
    shift; scriptpath="$1"; shift
    export RELEASE_ROOT_DIR

    "$ERTS_DIR/bin/escript" "$ROOTDIR/$scriptpath" $@
}

# Private. For determining the version of ERTS available to the release
_detect_erts_vsn() {
    erl -boot start_clean -eval 'Ver = erlang:system_info(version), io:format("~s~n", [Ver]), halt()' -noshell
}

# Private. For setting ERTS_DIR and ROOTDIR
_find_erts_dir() {
    __erts_dir="$RELEASE_ROOT_DIR/erts-$ERTS_VSN"
    if [ -d "$__erts_dir" ]; then
        ERTS_DIR="$__erts_dir";
        ROOTDIR="$RELEASE_ROOT_DIR"
    else
        __erl="$(which erl)"
        code="io:format(\"~s\", [code:root_dir()]), halt()."
        __erl_root="$("$__erl" -noshell -eval "$code")"
        ERTS_DIR="$__erl_root/erts-$ERTS_VSN"
        ROOTDIR="$__erl_root"
    fi
}

# Private. Open a shell on a remote node
_rem_sh() {
    # Generate a unique id used to allow multiple remsh to the same node
    # transparently
    id="remsh$(gen_id)-${NAME}"

    # Get the node's ticktime so that we use the same thing.
    TICKTIME="$(nodetool rpcterms net_kernel get_net_ticktime)"

    # Setup remote shell command to control node
    if [ ! -z "$USE_ERL_SHELL" ]; then
        exec "$BINDIR/erl" \
            -hidden \
            -boot start_clean -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -kernel net_ticktime $TICKTIME \
            "$NAME_TYPE" "$id" -remsh "$NAME" -setcookie "$COOKIE"
    else
        exec "$BINDIR/erl" \
            -pa "$ROOTDIR"/lib/*/ebin -pa "$CONSOLIDATED_DIR" \
            -hidden -noshell \
            -boot start_clean -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -kernel net_ticktime $TICKTIME \
            -user Elixir.IEx.CLI "$NAME_TYPE" "$id" -setcookie "$COOKIE" \
            -extra --no-halt +iex -"$NAME_TYPE" "$id" --cookie "$COOKIE" --remsh "$NAME"
    fi
}

# Output a start command for the last argument of run_erl
_start_command() {
    printf "exec \"%s\" \"%s\" -- %s %s" "$RELEASE_ROOT_DIR/bin/$REL_NAME" \
           "$START_OPTION" "${ARGS}" "${EXTRA_OPTS}"
}

# If ERTS_VSN is not set, detect it
if [ -z "$ERTS_VSN" ]; then
    ERTS_VSN="$(_detect_erts_vsn)"
    echo "$ERTS_VSN $REL_VSN" > "$START_ERL_DATA"
fi

# Allow override of where to look for config files
# By default it's $CWD/
if [ -z "$RELEASE_CONFIG_DIR" ]; then
    RELEASE_CONFIG_DIR="$RELEASE_ROOT_DIR"
fi

# Set VMARGS_PATH, the path to the vm.args file to use
# Use $RELEASE_CONFIG_DIR/vm.args if exists, otherwise releases/VSN/vm.args
if [ -z "$VMARGS_PATH" ]; then
    if [ -f "$RELEASE_CONFIG_DIR/vm.args" ]; then
        VMARGS_PATH="$RELEASE_CONFIG_DIR/vm.args"
    else
        VMARGS_PATH="$REL_DIR/vm.args"
    fi
fi

orig_vmargs_path="$VMARGS_PATH.orig"
if [ $REPLACE_OS_VARS ]; then
    #Make sure we don't break dev mode by keeping the symbolic link to
    #the user's vm.args
    if [ ! -L "$orig_vmargs_path" ]; then
       #we're in copy mode, rename the vm.args file to vm.args.orig
       mv "$VMARGS_PATH" "$orig_vmargs_path"
    fi

    awk '{while(match($0,"[$]{[^}]*}")) {var=substr($0,RSTART+2,RLENGTH -3);gsub("[$]{"var"}",ENVIRON[var])}}1' < "$orig_vmargs_path" > "$VMARGS_PATH"
 else
    #We don't need to replace env. vars, just rename the
    #symlink vm.args.orig to vm.args, and keep it as a
    #symlink.
    if [ -L "$orig_vmargs_path" ]; then
       mv "$orig_vmargs_path" "$VMARGS_PATH"
    fi
fi

# Make sure log directory exists
mkdir -p "$RUNNER_LOG_DIR"

# Set SYS_CONFIG_PATH, the path to the sys.config file to use
# Use $RELEASE_CONFIG_DIR/sys.config if exists, otherwise releases/VSN/sys.config
if [ -z "$SYS_CONFIG_PATH" ]; then
    if [ -f "$RELEASE_CONFIG_DIR/sys.config" ]; then
        SYS_CONFIG_PATH="$RELEASE_CONFIG_DIR/sys.config"
    else
        SYS_CONFIG_PATH="$REL_DIR/sys.config"
    fi
fi

orig_sys_config_path="$SYS_CONFIG_PATH.orig"
if [ $REPLACE_OS_VARS ]; then
    #Make sure we don't break dev mode by keeping the symbolic link to
    #the user's sys.config
    if [ ! -L "$orig_sys_config_path" ]; then
       #We're in copy mode, rename sys.config to sys.config.orig
       mv "$SYS_CONFIG_PATH" "$orig_sys_config_path"
    fi

    awk '{while(match($0,"[$]{[^}]*}")) {var=substr($0,RSTART+2,RLENGTH -3);gsub("[$]{"var"}",ENVIRON[var])}}1' < "$orig_sys_config_path" > "$SYS_CONFIG_PATH"
 else
    #We don't need to replace env. vars, just rename the
    #symlink sys.config.orig to sys.config. Keep it as
    #a symlink.
    if [ -L "$orig_sys_config_path" ]; then
       mv "$orig_sys_config_path"  "$SYS_CONFIG_PATH"
    fi
fi

# Extract the target node name from node.args
# Should be `-sname somename` or `-name somename@somehost`
NAME_ARG=$(egrep '^-s?name' "$VMARGS_PATH" || true)
if [ -z "$NAME_ARG" ]; then
    echo "vm.args needs to have either -name or -sname parameter."
    exit 1
fi

# Extract the name type and name from the NAME_ARG for REMSH
# NAME_TYPE should be -name or -sname
NAME_TYPE="$(echo "$NAME_ARG" | awk '{print $1}')"
# NAME will be either `somename` or `somename@somehost`
NAME="$(echo "$NAME_ARG" | awk '{print $2}')"

# Where the pipe will be stored when using `start`
# This is used so you can attach the running application to the current
# shell using `attach`
PIPE_DIR="${PIPE_DIR:-$RELEASE_ROOT_DIR/tmp/erl_pipes/$NAME/}"

# Extract the target cookie
COOKIE_ARG="$(grep '^-setcookie' "$VMARGS_PATH" || true)"
DEFAULT_COOKIE_FILE="$HOME/.erlang.cookie"
if [ -z "$COOKIE_ARG" ]; then
    if [ -f "$DEFAULT_COOKIE_FILE" ]; then
        COOKIE="$(cat "$DEFAULT_COOKIE_FILE")"
    else
        printf "a secret cookie must be provided in one of the following ways:\n  - with vm.args using the -setcookie parameter,\n  or\n  by writing the cookie to '$DEFAULT_COOKIE_FILE', with permissions set to 0400"
        exit 1
    fi
else
    # Extract cookie name from COOKIE_ARG
    COOKIE="$(echo "$COOKIE_ARG" | awk '{print $2}')"
fi

_find_erts_dir
export ROOTDIR="$RELEASE_ROOT_DIR"
export BINDIR="$ERTS_DIR/bin"
export EMU="beam"
export PROGNAME="erl"
export LD_LIBRARY_PATH="$ERTS_DIR/lib:$LD_LIBRARY_PATH"
ERTS_LIB_DIR="$ERTS_DIR/../lib"
CONSOLIDATED_DIR="$ROOTDIR/lib/${REL_NAME}-${REL_VSN}/consolidated"

cd "$ROOTDIR"

# User can specify an sname without @hostname
# This will fail when creating remote shell
# So here we check for @ and add @hostname if missing
case $NAME in
    *@*)
        # Nothing to do
        ;;
    *)
        NAME=$NAME@$(gen_nodename)
        ;;
esac

# Check the first argument for instructions
case "$1" in
    start|start_boot)

        # Make sure there is not already a node running
        #RES=`$NODETOOL ping`
        #if [ "$RES" = "pong" ]; then
        #    echo "Node is already running!"
        #    exit 1
        #fi
        # Save this for later.
        CMD=$1
        case "$1" in
            start)
                shift
                START_OPTION="console"
                HEART_OPTION="start"
                ;;
            start_boot)
                shift
                START_OPTION="console_boot"
                HEART_OPTION="start_boot"
                ;;
        esac
        ARGS="$@"
        RUN_PARAM="$@"

        [ -f "$PRE_START_HOOK" ] && . "$PRE_START_HOOK"

        # Set arguments for the heart command
        set -- "$SCRIPT_DIR/$REL_NAME" "$HEART_OPTION"
        [ "$RUN_PARAM" ] && set -- "$@" "$RUN_PARAM"

        # Export the HEART_COMMAND
        HEART_COMMAND="$RELEASE_ROOT_DIR/bin/$REL_NAME $CMD"
        export HEART_COMMAND

        mkdir -p "$PIPE_DIR"

        "$BINDIR/run_erl" -daemon "$PIPE_DIR" "$RUNNER_LOG_DIR" \
                          "$(_start_command)"

        [ -f "$POST_START_HOOK" ] && . "$POST_START_HOOK"
        ;;

    stop)
        [ -f "$PRE_STOP_HOOK" ] && . "$PRE_STOP_HOOK"
        # Wait for the node to completely stop...
        PID="$(get_pid)"
        if ! nodetool "stop"; then
            exit 1
        fi
        while $(kill -s 0 "$PID" 2>/dev/null);
        do
            sleep 1
        done
        [ -f "$POST_STOP_HOOK" ] && . "$POST_STOP_HOOK"
        ;;

    restart)
        [ -f "$PRE_START_HOOK" ] && . "$PRE_START_HOOK"
        ## Restart the VM without exiting the process
        if ! nodetool "restart"; then
            exit 1
        fi
        ;;

    reboot)
        [ -f "$PRE_START_HOOK" ] && . "$PRE_START_HOOK"
        ## Restart the VM completely (uses heart to restart it)
        if ! nodetool "reboot"; then
            exit 1
        fi
        ;;

    pid)
        ## Get the VM's pid
        if ! get_pid; then
            exit 1
        fi
        ;;

    ping)
        ## See if the VM is alive
        if ! nodetool "ping"; then
            exit 1
        fi
        ;;

    escript)
        ## Run an escript under the node's environment
        if ! escript $@; then
            exit 1
        fi
        ;;

    attach)
        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift
        exec "$BINDIR/to_erl" "$PIPE_DIR"
        ;;

    remote_console)
        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift
        _rem_sh
        ;;

    upgrade|downgrade|install)
        if [ -z "$2" ]; then
            echo "Missing package argument"
            echo "Usage: $REL_NAME $1 {package base name}"
            echo "NOTE {package base name} MUST NOT include the .tar.gz suffix"
            exit 1
        fi

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        exec "$BINDIR/escript" "$ROOTDIR/bin/install_upgrade.escript" \
             "install" "$REL_NAME" "$NAME_TYPE" "$NAME" "$COOKIE" "$2"
        ;;

    unpack)
        if [ -z "$2" ]; then
            echo "Missing package argument"
            echo "Usage: $REL_NAME $1 {package base name}"
            echo "NOTE {package base name} MUST NOT include the .tar.gz suffix"
            exit 1
        fi

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        exec "$BINDIR/escript" "$ROOTDIR/bin/install_upgrade.escript" \
             "unpack" "$REL_NAME" "$NAME_TYPE" "$NAME" "$COOKIE" "$2"
        ;;

    console|console_clean|console_boot)
        # .boot file typically just $REL_NAME (ie, the app name)
        # however, for debugging, sometimes start_clean.boot is useful.
        # For e.g. 'setup', one may even want to name another boot script.
        case "$1" in
            console)
                if [ -f "$REL_DIR/$REL_NAME.boot" ]; then
                  BOOTFILE="$REL_DIR/$REL_NAME"
                else
                  BOOTFILE="$REL_DIR/start"
                fi
                ;;
            console_clean)
                BOOTFILE="$ROOTDIR/bin/start_clean"
                ;;
            console_boot)
                shift
                BOOTFILE="$1"
                shift
                ;;
        esac
        # Setup beam-required vars
        EMU="beam"
        PROGNAME="${0#*/}"

        export EMU
        export PROGNAME

        # Store passed arguments since they will be erased by `set`
        ARGS="$@"

        # Start the VM, executing pre_start hook along
        # the way. We can't run the post_start hook because
        # the console will crash with no TTY attached
        [ -f "$PRE_START_HOOK" ] && . "$PRE_START_HOOK"

        # Build an array of arguments to pass to exec later on
        # Build it here because this command will be used for logging.
        set -- "$BINDIR/erlexec" \
            -boot "$BOOTFILE" \
            -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -env ERL_LIBS "$REL_LIB_DIR" \
            -pa "$CONSOLIDATED_DIR" \
            -args_file "$VMARGS_PATH" \
            -config "$SYS_CONFIG_PATH" \
            -mode "$CODE_LOADING_MODE" \
            ${ERL_OPTS} \
            -user Elixir.IEx.CLI \
            -extra --no-halt +iex

        # Dump environment info for logging purposes
        echo "Exec: $@" -- ${1+$ARGS} ${EXTRA_OPTS}
        echo "Root: $ROOTDIR"

        # Log the startup
        echo "$RELEASE_ROOT_DIR"
        logger -t "$REL_NAME[$$]" "Starting up"

        exec "$@" -- ${1+$ARGS} ${EXTRA_OPTS}
        ;;

    foreground)
        # start up the release in the foreground for use by runit
        # or other supervision services

        [ -f "$REL_DIR/$REL_NAME.boot" ] && BOOTFILE="$REL_NAME" || BOOTFILE=start
        FOREGROUNDOPTIONS="-noshell -noinput +Bd"

        # Setup beam-required vars
        EMU=beam
        PROGNAME="${0#*/}"

        export EMU
        export PROGNAME

        # Store passed arguments since they will be erased by `set`
        ARGS="$@"

        # Start the VM, executing pre and post start hooks
        [ -f "$PRE_START_HOOK" ] && . "$PRE_START_HOOK"

        # Build an array of arguments to pass to exec later on
        # Build it here because this command will be used for logging.
        set -- "$BINDIR/erlexec" $FOREGROUNDOPTIONS \
            -boot "$REL_DIR/$BOOTFILE" -mode "$CODE_LOADING_MODE" -config "$SYS_CONFIG_PATH" \
            -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -args_file "$VMARGS_PATH" \
            -env ERL_LIBS "$REL_LIB_DIR" \
            -pa "$CONSOLIDATED_DIR" \
            ${ERL_OPTS} \
            -extra ${EXTRA_OPTS}

        # Dump environment info for logging purposes
        echo "Exec: $@" -- ${1+$ARGS}
        echo "Root: $ROOTDIR"

        trap '{}' QUIT TERM KILL HUP SIGUSR1 SIGUSR2
        "$@" -- ${1+$ARGS} &
        __bg_pid=$!
        [ -f "$POST_START_HOOK" ] && . "$POST_START_HOOK"
        wait $__bg_pid
        ;;
    rpc)
        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift

        nodetool rpc $@
        ;;
    rpcterms)
        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift

        nodetool rpcterms $@
        ;;
    eval)
        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift
        nodetool "eval" $@
        ;;
    command)
        # Execute as command-line utility
        #
        # Like the escript command, this does not start the OTP application.
        # If your command depends on a running OTP application,
        # use
        #
        #     {:ok, _} = Application.ensure_all_started(:your_app)

        shift
        MODULE="$1"; shift
        FUNCTION="$1"; shift

        # Save extra arguments
        ARGS="$@"

        # Build arguments for erlexec
        set -- "$ERL_OPTS"
        [ "$SYS_CONFIG_PATH" ] && set -- "$@" -config "$SYS_CONFIG_PATH"
        set -- "$@" -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR"
        set -- "$@" -noshell
        set -- "$@" -boot start_clean
        set -- "$@" -s "$MODULE" "$FUNCTION"

        $BINDIR/erlexec $@ -extra $ARGS
        exit "$?"
        ;;
    *)
        __command_path="$REL_DIR/commands/$1"
        if [ -f "$__command_path" ]; then
            . "$__command_path"
        else
            echo "Usage: $REL_NAME {start|start_boot <file>|foreground|stop|restart|reboot|pid|ping|console|console_clean|console_boot <file>|attach|remote_console|upgrade|downgrade|install|escript|rpc|rpcterms|eval|command <module> <function> <args>}"
            exit 1
        fi
        ;;
esac

exit 0


/auth/logout link

/auth/logout link


landing text

landing text

A liquid democracy where anyone can vote on anything.

	Explore polls

Key features

				Delegations

				Not everyone is an expert at everything. That's why you can delegate your vote to people you trust.

				References

				References aim to help voters make more informed decisions. They also allow people not familiar with the subject to quickly learn about it.

				Trust metrics

				Trust metrics attempt to prevent a single person from having multiple identities. Everyone can choose their own trust metric or create a new one.

				Objectivity

				References and delegations work very well with objective polls. Things like your favourite ice cream flavour don't work.

				No censorship

				All subjective logic lives inside a trust metric. The default trust metric lives here. You can always choose a different trust metric.

				Transparency

				The source code is available under permissive MIT license. All the data is publicly available through the API.

Examples

				<%= for poll <- @examples do %>

						<a href="/polls/<%= poll.id %>">

<%= poll.title %>

							<div class="score" style="background-color: <%= Liquio.HtmlPollView.score_color poll %>;">
								<%= if poll.results.mean do %>
									<%= if poll.choice_type == "probability" do %>
										<%= round(poll.results.mean * 100) %>%
									<% else %>
										<%= number_format(poll.results.mean) %>
									<% end %>
								<% else %>
									?
								<% end %>

				<% end %>

	Liquio is still in early development. You can view the source code on GitHub. Feedback and contributions are welcome.

A liquid democracy where anyone can vote on anything.

	Explore polls

Key features

				Delegations

				Not everyone is an expert at everything. That's why you can delegate your vote to people you trust.

				References

				References aim to help voters make more informed decisions. They also allow people not familiar with the subject to quickly learn about it.

				Trust metrics

				Trust metrics attempt to prevent a single person from having multiple identities. Everyone can choose their own trust metric or create a new one.

				Objectivity

				Liquio encourages polls that aren't purely subjective.

				No moderation

				All subjective logic lives inside a trust metric. Take a look at default trust metric. You can easily change it to anything you like.

				Transparency

				The source code is available under permissive MIT license. All the data is publicly available through the API.

Examples

				<%= for poll <- @examples do %>

						<a href="/polls/<%= poll.id %>">

<%= poll.title %>

							<div class="score" style="background-color: <%= Liquio.HtmlPollView.score_color poll %>;">
								<%= if poll.results.mean do %>
									<%= if poll.choice_type == "probability" do %>
										<%= round(poll.results.mean * 100) %>%
									<% else %>
										<%= number_format(poll.results.mean) %>
									<% end %>
								<% else %>
									?
								<% end %>

				<% end %>

	Liquio is still in early development. You can view the source code on GitHub. Feedback and contributions are welcome.


fix 'characters left' for all chapters

fix 'characters left' for all chapters

<%= if @current_user do %>

    <%= form_for @changeset, recommendation_frontend_path(@conn, :create), fn f -> %>

        <%= label f, "Your recommendation:", class: "control-label" %>
        <%= text_input f, :comment, class: "form-control", maxlength: 255,
                                    data: [chapter: @chapter.id ]  %>

<span id='remaining<%=@chapter.id %>'>255 characters left

      <%= hidden_input f, :chapter_id, value: @chapter.id  %>

        <%= submit [fa_icon("thumbs-o-up"), " Recommend"], class: "btn btn-primary" %>

    <% end %>

<% end %>

<%= if @current_user do %>

    <%= form_for @changeset, recommendation_frontend_path(@conn, :create), fn f -> %>

        <%= label f, "Your recommendation:", class: "control-label" %>
        <%= text_input f, :comment, class: "form-control", maxlength: 255  %>
        <pclass="help-block">255 characters left

      <%= hidden_input f, :chapter_id, value: @chapter.id  %>

        <%= submit [fa_icon("thumbs-o-up"), " Recommend"], class: "btn btn-primary" %>

    <% end %>

<% end %>


Add intro copy to root

Add intro copy to root

    Get Better With Your Team

Remote Retro lets you get together, even when you're far apart.

  <%= form_for @conn, retro_path(@conn, :create), [as: :retro, class: "ui form"], fn _f -> %>
    <%= submit "Create a Retrospective", class: "ui tiny button teal" %>
  <% end %>

<%= form_for @conn, retro_path(@conn, :create), [as: :retro, class: "ui form basic segment"], fn _f -> %>
  <%= submit "Create a Retrospective", class: "ui button teal" %>
<% end %>


Update html header

Update html header

<!DOCTYPE html>

<meta charset="utf-8">
<title>Index of <%= Plug.HTML.html_escape(directory_path) %></title>

Index of <%= Plug.HTML.html_escape(directory_path) %>


Remove equal sign from eex end

Remove equal sign from eex end

          <%= link(@post.title, to: post_path(@conn, :show, @post)) %>

        <%= raw Tilex.Markdown.to_html(@post.body) %>

        <%= if action_name(@conn) == :show do %>
          <a href='http://twitter.com/share'
             class='twitter-share-button'
             data-text= "Today I learned: <%= @post.title %>"
             data-via= "<%= @post.developer.twitter_handle %>"
             data-hashtags= "<%= @post.channel.twitter_hashtag %>"
             data-url= "<%= post_url(@conn, :show, @post) %>">
            Tweet

        <% end %>

            <%= link(@post.developer.username, to: developer_path(@conn, :show, @post.developer)) %>

            <%= link(display_date(@post), to: post_path(@conn, :show, @post), class: "post__permalink") %>

            <%= link("##{@post.channel.name}", to: channel_path(@conn, :show, @post.channel.name), class: "post__tag-link") %>

            <%= link("permalink", to: post_path(@conn, :show, @post), class: "post__permalink") %>

          <%= if Guardian.Plug.current_resource(@conn) && (@post.developer == Guardian.Plug.current_resource(@conn) || Guardian.Plug.current_resource(@conn).admin) do %>

              <%= link("edit", to: post_path(@conn, :edit, @post), class: "post__permalink") %>

          <% end %>

            <%= link to: "#", class: "js-like-action post__like-link", id: @post.slug do %>
              <%= @post.likes %>
              likes
            <% end %>

          <%= link(@post.title, to: post_path(@conn, :show, @post)) %>

        <%= raw Tilex.Markdown.to_html(@post.body) %>

        <%= if action_name(@conn) == :show do %>
          <a href='http://twitter.com/share'
             class='twitter-share-button'
             data-text= "Today I learned: <%= @post.title %>"
             data-via= "<%= @post.developer.twitter_handle %>"
             data-hashtags= "<%= @post.channel.twitter_hashtag %>"
             data-url= "<%= post_url(@conn, :show, @post) %>">
            Tweet

        <%= end %>

            <%= link(@post.developer.username, to: developer_path(@conn, :show, @post.developer)) %>

            <%= link(display_date(@post), to: post_path(@conn, :show, @post), class: "post__permalink") %>

            <%= link("##{@post.channel.name}", to: channel_path(@conn, :show, @post.channel.name), class: "post__tag-link") %>

            <%= link("permalink", to: post_path(@conn, :show, @post), class: "post__permalink") %>

          <%= if Guardian.Plug.current_resource(@conn) && (@post.developer == Guardian.Plug.current_resource(@conn) || Guardian.Plug.current_resource(@conn).admin) do %>

              <%= link("edit", to: post_path(@conn, :edit, @post), class: "post__permalink") %>

          <% end %>

            <%= link to: "#", class: "js-like-action post__like-link", id: @post.slug do %>
              <%= @post.likes %>
              likes
            <% end %>


Basic box plotting way too easy... <3

Basic box plotting way too easy... <3

<!DOCTYPE html>

    <meta http-equiv="content-type" content="text/html; charset=utf8">

Comparison

Data Table

              Name
              Iterations per Second
              Average
              Deviation
              median

            <%= for {name, statistics} <- suite.statistics do %>

                <%= name %>
                <%= statistics.ips %>
                <%= statistics.average %>
                <%= statistics.std_dev_ratio %>%
                <%= statistics.median %>

            <% end %>

Iterations per Second

Runtime Box Plot

    <%= for {name, _} <- suite.run_times do %>

 <%= name %>

 Run time Histogram

          <div class="sorted-run-times" data-job-name="<%= name %>">

 Raw run times

          <div class="raw-run-times" data-job-name="<%= name %>">

    <% end %>

<!DOCTYPE html>

    <meta http-equiv="content-type" content="text/html; charset=utf8">

Comparison

Data Table

              Name
              Iterations per Second
              Average
              Deviation
              median

            <%= for {name, statistics} <- suite.statistics do %>

                <%= name %>
                <%= statistics.ips %>
                <%= statistics.average %>
                <%= statistics.std_dev_ratio %>%
                <%= statistics.median %>

            <% end %>

Iterations per Second Comparison

    <%= for {name, _} <- suite.run_times do %>

 <%= name %>

 Run time Histogram

          <div class="sorted-run-times" data-job-name="<%= name %>">

 Raw run times

          <div class="raw-run-times" data-job-name="<%= name %>">

    <% end %>


Set event background div to to 100% in event list

Erlang Ecosystem Foundation

Supporting the next generation of advanced, reliable, realtime applications

The Erlang Ecosystem Foundation is a 501(c)(3) not-for-profit organization supported by over 100 members who embrace the foundations' collaborative Working Group model, and community-building events.

Our members include industry leaders who are dedicated to furthering state of the art for Erlang, Elixir, LFE and other technologies based on the BEAM.

                        Join Now →

Upcoming Events

                        <%= for event <- @events do %>

                                <div style="background-color: <%= event.organizer_brand_color %>; height: 100%; width: 6rem;" class="p-2 p-md-4 mr-4 rounded-left event-card-image-wrapper d-flex align-items-center">
                                    <img src="<%= event.organizer_brand_logo %>" class="img-fluid d-block mx-auto event-card-list-image" alt="">

                                        <%= link(event.title, to: event.url, class: "text-dark font-weight-bold") %>

<%= event_dates(event.start, event.end) %>

                        <% end %>

                        View All Events →

                    <%= right_svg_hero() do %>

                    <% end %>

Latest news

            <%= render(ErlefWeb.LayoutView, "twitter_feed.html", assigns) %>

        <%= render(ErlefWeb.LayoutView, "news_feed.html", assigns) %>

What does the Erlang Ecosystem Foundation do?

                        In order to meet the needs of the ecosystem, the ErlEF sponsors Working Groups to solve specific challenges faced by users of BEAM technology. Areas of particular interest include documentation, interoperability, and performance.

            <%= render(ErlefWeb.LayoutView, "working_groups.html", assigns) %>

      <% full_url = ErlefWeb.Endpoint.url()  <> Routes.page_path(@conn, :all_calendars) %>
      <% parsed = URI.parse(full_url) %>
      <% webcal = parsed.host <> parsed.path %>

        <a href="webcal://<%= webcal %>">Subscribe to this calendar

        <%= calendar(Routes.page_path(@conn, :all_calendars)) %>

      <%= render(ErlefWeb.LayoutView, "subscribe.html", assigns) %>

Erlang Ecosystem Foundation

Supporting the next generation of advanced, reliable, realtime applications

The Erlang Ecosystem Foundation is a 501(c)(3) not-for-profit organization supported by over 100 members who embrace the foundations' collaborative Working Group model, and community-building events.

Our members include industry leaders who are dedicated to furthering state of the art for Erlang, Elixir, LFE and other technologies based on the BEAM.

                        Join Now →

Upcoming Events

                        <%= for event <- @events do %>

                                <div style="background-color: <%= event.organizer_brand_color %>; width: 6rem;" class="p-2 p-md-4 mr-4 rounded-left event-card-image-wrapper d-flex align-items-center">
                                    <img src="<%= event.organizer_brand_logo %>" class="img-fluid d-block mx-auto event-card-list-image" alt="">

                                        <%= link(event.title, to: event.url, class: "text-dark font-weight-bold") %>

<%= event_dates(event.start, event.end) %>

                        <% end %>

                        View All Events →

                    <%= right_svg_hero() do %>

                    <% end %>

Latest news

            <%= render(ErlefWeb.LayoutView, "twitter_feed.html", assigns) %>

        <%= render(ErlefWeb.LayoutView, "news_feed.html", assigns) %>

What does the Erlang Ecosystem Foundation do?

                        In order to meet the needs of the ecosystem, the ErlEF sponsors Working Groups to solve specific challenges faced by users of BEAM technology. Areas of particular interest include documentation, interoperability, and performance.

            <%= render(ErlefWeb.LayoutView, "working_groups.html", assigns) %>

      <% full_url = ErlefWeb.Endpoint.url()  <> Routes.page_path(@conn, :all_calendars) %>
      <% parsed = URI.parse(full_url) %>
      <% webcal = parsed.host <> parsed.path %>

        <a href="webcal://<%= webcal %>">Subscribe to this calendar

        <%= calendar(Routes.page_path(@conn, :all_calendars)) %>

      <%= render(ErlefWeb.LayoutView, "subscribe.html", assigns) %>


Fix table headers in admin

Fix table headers in admin

      #
      Date
      Title
      frontpage
      rss
      detail
      via shortlink
      clicks in post

  <%= for posting <- @postings do %>

      <%= posting.id %>
      <%= human_readable_date posting.published_at %>
      <%= link ElixirStatus.Publisher.short_title(posting.title, 30), to: permalink_posting_path(@conn, :show, posting.permalink), title: sanitized_inline_markdown(posting.title) %>

        <%= ElixirStatus.Impressionist.count_sessions "frontpage", "posting", posting.uid %>

          /
          <%= ElixirStatus.Impressionist.count "frontpage", "posting", posting.uid %>

        <%= ElixirStatus.Impressionist.count_sessions "rss", "posting", posting.uid %>

        <%= ElixirStatus.Impressionist.count_sessions "detail", "posting", posting.uid %>

          /
          <%= ElixirStatus.Impressionist.count "detail", "posting", posting.uid %>

        <%= ElixirStatus.Impressionist.count_sessions "detail", "short_link", to_short_uid(posting.permalink) %>

          /
          <%= ElixirStatus.Impressionist.count "detail", "short_link", to_short_uid(posting.permalink) %>

        <%= ElixirStatus.Impressionist.count_sessions "postings:#{posting.uid}", "short_link" %>

          /
          <%= ElixirStatus.Impressionist.count "postings:#{posting.uid}", "short_link" %>

  <% end %>

      #
      Title
      frontpage
      rss
      detail
      via shortlink
      clicks in post

  <%= for posting <- @postings do %>

      <%= posting.id %>
      <%= human_readable_date posting.published_at %>
      <%= link ElixirStatus.Publisher.short_title(posting.title, 30), to: permalink_posting_path(@conn, :show, posting.permalink), title: sanitized_inline_markdown(posting.title) %>

        <%= ElixirStatus.Impressionist.count_sessions "frontpage", "posting", posting.uid %>

          /
          <%= ElixirStatus.Impressionist.count "frontpage", "posting", posting.uid %>

        <%= ElixirStatus.Impressionist.count_sessions "rss", "posting", posting.uid %>

        <%= ElixirStatus.Impressionist.count_sessions "detail", "posting", posting.uid %>

          /
          <%= ElixirStatus.Impressionist.count "detail", "posting", posting.uid %>

        <%= ElixirStatus.Impressionist.count_sessions "detail", "short_link", to_short_uid(posting.permalink) %>

          /
          <%= ElixirStatus.Impressionist.count "detail", "short_link", to_short_uid(posting.permalink) %>

        <%= ElixirStatus.Impressionist.count_sessions "postings:#{posting.uid}", "short_link" %>

          /
          <%= ElixirStatus.Impressionist.count "postings:#{posting.uid}", "short_link" %>

  <% end %>


remove empty panel

remove empty panel

    <%= if @categories != [] do %>

Categories

          <%= for category <- @categories do %>
            <%= link [fa_icon("folder-o"), " ", category.title],
                     to: category_frontend_path(@conn, :show, category),
                     class: "btn btn-primary btn-xs" %>
          <% end %>

    <% end %>

<%= Enum.count(@podcasts.entries) %> Podcasts out of <%= @podcasts.total_entries %>

        <%= pagination_links @conn, @podcasts,
                       path: &search_frontend_path/3,
                       action: :new,
                       search: %{searchstring: @searchstring},
                       view_style: :bootstrap %>

        <%= for podcast <- @podcasts.entries do %>

            <%= link [fa_icon("podcast"), " ", podcast.title],
                     to: podcast_frontend_path(@conn, :show, podcast.id),
                     class: "btn btn-default btn-xs", style: "color: #000" %>

            <%= podcast_hits(podcast, @searchstring) %>

        <% end %>

<%= Enum.count(@episodes.entries) %> Episodes out of <%= @episodes.total_entries %>

        <%= pagination_links @conn, @episodes,
                       path: &search_frontend_path/3,
                       action: :new,
                       search: %{searchstring: @searchstring},
                       view_style: :bootstrap %>

        <%= for episode <- @episodes.entries do %>

            <%= link [fa_icon("headphones"), " ", episode.title],
                     to: episode_frontend_path(@conn, :show, episode.id),
                     class: "btn btn-default btn-xs", style: "color: #000" %>

            <%= episode_hits(episode, @searchstring) %>

        <% end %>

    <%= if @categories do %>

Categories

          <%= for category <- @categories do %>
            <%= link [fa_icon("folder-o"), " ", category.title],
                     to: category_frontend_path(@conn, :show, category),
                     class: "btn btn-primary btn-xs" %>
          <% end %>

    <% end %>

<%= Enum.count(@podcasts.entries) %> Podcasts out of <%= @podcasts.total_entries %>

        <%= pagination_links @conn, @podcasts,
                       path: &search_frontend_path/3,
                       action: :new,
                       search: %{searchstring: @searchstring},
                       view_style: :bootstrap %>

        <%= for podcast <- @podcasts.entries do %>

            <%= link [fa_icon("podcast"), " ", podcast.title],
                     to: podcast_frontend_path(@conn, :show, podcast.id),
                     class: "btn btn-default btn-xs", style: "color: #000" %>

            <%= podcast_hits(podcast, @searchstring) %>

        <% end %>

<%= Enum.count(@episodes.entries) %> Episodes out of <%= @episodes.total_entries %>

        <%= pagination_links @conn, @episodes,
                       path: &search_frontend_path/3,
                       action: :new,
                       search: %{searchstring: @searchstring},
                       view_style: :bootstrap %>

        <%= for episode <- @episodes.entries do %>

            <%= link [fa_icon("headphones"), " ", episode.title],
                     to: episode_frontend_path(@conn, :show, episode.id),
                     class: "btn btn-default btn-xs", style: "color: #000" %>

            <%= episode_hits(episode, @searchstring) %>

        <% end %>


Added gumroad script tag

Added gumroad script tag

<!DOCTYPE html>

    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <%= render_existing(@view_module, "meta." <> @view_template, assigns) || render(Ap.LayoutView, "meta.html", assigns) %>

    <link rel="dns-prefetch" href="//res.cloudinary.com">

    <%= render Ap.LayoutView, "common_social_meta.html" %>
    <%= render_existing(@view_module, "social_meta." <> @view_template, assigns) || render(Ap.LayoutView, "social_meta.html", assigns) %>

    <link rel="icon" href="/favicon.ico" />
    <link rel="icon" href="/images/favicon.png" sizes="16x16" type="image/png">

    <%= if Mix.env == :prod do %>

    <% end %>

    <link rel="stylesheet" href="<%= static_path(@conn, "/css/frontend.css") %>">

    <meta name="msvalidate.01" content="3F3F0DA3D9FF8AE3DA64D767717C782B" />

    <%= render Ap.SharedView, "header.html", conn: @conn, product_categories: @product_categories %>

          <%= show_flash(@conn) %>
          <%= render @view_module, @view_template, assigns %>

    <%= render Ap.SharedView, "footer.html", conn: @conn %>


structured data markup to indicate the preferred name for Google

https://developers.google.com/search/docs/data-types/sitename


Center background images

Center background images

 Candidates

    We are excited to announce our first candidates! Join us to be notified of many more candidates in the weeks to come.

    <%= for cand <- @candidates do %>
      <div class="card" href="<%= cand.external_website %>">

          <%= cand.title %>

        <div class="cand-image" style="width: 100%; height: 234px; overflow: hidden; background-position: center; background-image: url(<%= cand.small_picture %>)">

          <%= cand.district %>

          <%= cand.website_blurb %>
          <a href="<%= cand.external_website %>">Read More

    <% end %>

 Candidates

    We are excited to announce our first candidates! Join us to be notified of many more candidates in the weeks to come.

    <%= for cand <- @candidates do %>
      <div class="card" href="<%= cand.external_website %>">

          <%= cand.title %>

        <div class="cand-image" style="width: 100%; height: 234px; overflow: hidden; background-image: url(<%= cand.small_picture %>)">

          <%= cand.district %>

          <%= cand.website_blurb %>
          <a href="<%= cand.external_website %>">Read More

    <% end %>


Fixing the size of the buttons

Fixing the size of the buttons

            <%= link "Sort by Fresh", to: task_path(@conn, :index, sort: "fresh"), class: "mdl-button mdl-js-button mdl-button--raised" %>

            <%= link "Sort by Closest", to: task_path(@conn, :index, sort: "closest"), class: "mdl-button mdl-js-button mdl-button--raised" %>

<%= render "index_volunteer_tasks_generic.html", tasks: @your_tasks, section_title: "Your tasks", available_actions: [:show, :drop], conn: @conn %>

<%= render "index_volunteer_tasks_generic.html", tasks: @available_tasks, section_title: "Available tasks", available_actions: [:show, :grab], conn: @conn %>

<%= render "index_volunteer_tasks_generic.html", tasks: @your_past_tasks, section_title: "Your pasts tasks", available_actions: [:show], conn: @conn %>


Issue 27: added warning about deleting a cfp will delete the submissions

Listing callforpapers

      Start
      End
      Status
      Conference

<%= for callforpapers <- @callforpapers do %>

      <%= callforpapers.start %>
      <%= callforpapers.end %>

          <%= if callforpapers.status == "open" do %>
            <%= fa_icon("unlock") %>
          <% else %>
            <%= fa_icon("lock") %>
          <% end %>

      <%= callforpapers.conference.title %>

        <%= if Callforpapers.User.is_organizer?(@current_user) do %>
          <%= if callforpapers.status == "open" do %>
            <%= link fw_icon("lock"), title: "Close", to: callforpapers_path(@conn, :edit, callforpapers) %>
          <% else %>
            <%= link fw_icon("unlock"), title: "Open", to: callforpapers_path(@conn, :edit, callforpapers) %>
          <% end %>
        <% end %>

        <%= link fw_icon("eye"), title: "Show", to: callforpapers_path(@conn, :show, callforpapers) %>
        <%= if Callforpapers.User.is_organizer?(@current_user) do %>
          <%= link fw_icon("pencil"), title: "Edit", to: callforpapers_path(@conn, :edit, callforpapers) %>
          <%= link fw_icon("trash"), title: "Delete", to: callforpapers_path(@conn, :delete, callforpapers), method: :delete, data: [confirm: "Are you sure? All submissions to this cfp will be delted, too."] %>
        <% else %>
          <%= link fw_icon("send"), title: "Submit talk", to: submission_path(@conn, :new) %>
        <% end %>

<% end %>

<%= if Callforpapers.User.is_organizer?(@current_user) do %>
  <%= link fa_icon("plus-square 2x"), title: "New CfP", to: callforpapers_path(@conn, :new) %>
<% end %>

Listing callforpapers

      Start
      End
      Status
      Conference

<%= for callforpapers <- @callforpapers do %>

      <%= callforpapers.start %>
      <%= callforpapers.end %>

          <%= if callforpapers.status == "open" do %>
            <%= fa_icon("unlock") %>
          <% else %>
            <%= fa_icon("lock") %>
          <% end %>

      <%= callforpapers.conference.title %>

        <%= if Callforpapers.User.is_organizer?(@current_user) do %>
          <%= if callforpapers.status == "open" do %>
            <%= link fw_icon("lock"), title: "Close", to: callforpapers_path(@conn, :edit, callforpapers) %>
          <% else %>
            <%= link fw_icon("unlock"), title: "Open", to: callforpapers_path(@conn, :edit, callforpapers) %>
          <% end %>
        <% end %>

        <%= link fw_icon("eye"), title: "Show", to: callforpapers_path(@conn, :show, callforpapers) %>
        <%= if Callforpapers.User.is_organizer?(@current_user) do %>
          <%= link fw_icon("pencil"), title: "Edit", to: callforpapers_path(@conn, :edit, callforpapers) %>
          <%= link fw_icon("trash"), title: "Delete", to: callforpapers_path(@conn, :delete, callforpapers), method: :delete, data: [confirm: "Are you sure?"] %>
        <% else %>
          <%= link fw_icon("send"), title: "Submit talk", to: submission_path(@conn, :new) %>
        <% end %>

<% end %>

<%= if Callforpapers.User.is_organizer?(@current_user) do %>
  <%= link fa_icon("plus-square 2x"), title: "New CfP", to: callforpapers_path(@conn, :new) %>
<% end %>


Fix workshop confirmation email

Fix workshop confirmation email

  <%= @title %>

Hello <%= @name %>,

You have just confirmed your presence in the Make or Break workshop:

<%= @workshop.name %>

      If, for some reason, you can’t attend, you should leave the workshop as soon as possible, by visiting the workshop page <a href="https://makeorbreak.io/#workshop-<%= @workshop.slug %>">here

      See you in Porto!

      The Make or Break team

  <%= @title %>

Hello <%= @name %>,

You have just confirmed your presence in the Make or Break workshop:

<%= @workshop.name %>

      If, for some reason, you can’t attend, you should leave the workshop as soon as possible, by visiting the workshop page <a href="https://makeorbreak.io/#workshop-#{<%= @workshop.slug %>}">here

      See you in Porto!

      The Make or Break team


Minor FAQ fixes

Minor FAQ fixes

<%= gettext "FAQ" %>

<%= gettext "What is data protection?" %>

<%= gettext "Data protection is a human right in the European Union. It’s a collection of administrative and formal requirements for how to collect, process and use data relating to individuals. The purpose of this protection is to provide individuals with the means necessary to exercise their right to privacy. Data protection law guarantees transparency, choice and knowledge for individuals with regards to who influences them, and under which conditions." %>

<%= gettext "In May 2018 a new law about data protection will enter into force in the European Union. It is a regulation and will apply equally in all the 28 member states." %>

<%= gettext "What is ”behavioural monitoring”?" %>

<%= gettext "Behavioural monitoring, or ”profiling”, is when someone monitors how a given person, or set of persons, typically behave. This includes monitoring whether a particular group, say young people or women of a median income, frequently visit certain deeplinks, have to look up certain vocabulary or that they end up on the website through using a particular search engine or social platform. Behavioural monitoring is used to discover what certain classes of people may be assumed to find interesting, difficult or funny." %>

<%= gettext "It is also the categorisation of individuals into these groups. Once a web visitor is stuffed into a particular category, they may be positively or negatively discriminated against because of the categorisation." %>

<%= gettext "Profiling is mostly used in the advertisement industry to decide which type of advertisements a particular individual should be exposed to. Parents of small children, or people who know parents of small children, may receive ads for nappies, prams or family vacations. Increasingly, profiling is used to determine what contents are served by newspapers. The above mentioned groups may for instance receive short articles about new-borns if they are queueing (and have little time) or longer articles about new-borns if they are on a train (and have more time)." %>

<%= gettext "Profiling may additionally be used to shape political opinions, for instance through targeting specific groups with political information, or to enact measures against groups based on their assumed characteristics. This form of political work is called ”nudging” and may also be deployed to increase acceptance of specific measures (like the construction of a public park) in specific groups (such as the individuals living near the envisaged park)." %>

<%= gettext "What do you mean by ”gossiping to third-parties”?" %>

<%= gettext "We use the word gossiping to mean that information about somebody’s behaviour, reading habits or preferences is handed over to somebody other than the actor responsible for the website." %>

<%= gettext "In modern web development, it’s become common for a website not to be run from only one location. When you visit a website, you’re not only entering into contact with those running the website, but also all the businesses and organisations which collaborate with the managers of the websites. These may be internet service providers, script providers, font providers, analytics tools providers and a range of other providers. If the manager of the websites hands over information about visitors to any of these third-parties, it is a form of gossiping since it is usually not evident to the visitors that this type of information is being handed over." %>

<%= gettext "A webstore may for instance hand over the task of profiling visitors to an advertisement agency, and a public authority may have constructed its website in a way that automatically hands over behavioural data to advertisers. Advertisers are the most common and least transparent form of third parties." %>

<%= gettext "What are the principles of the EU general data protection regulation?" %>

<%= gettext(~s|The general data protection regulation of the European Union enters into force on the 25th of May 2018 and concerns the balancing of power being those influencing individuals (typically companies and public authorities) and the individuals themselves. Webbkoll is a tool to find out who is collecting information about individuals, and what can be done to stop invisible tracking.|) |> raw %>

<%= gettext "Lawfulness, fairness and transparency" %>

<%= gettext "An individual should be able to understand the terms of interactions with others. (5(1)(a))." %>

<%= gettext "Webbkoll sees lawfulness, fairness and transparency as a requirement that individuals should understand with whom they are in contact by visiting a website. If an advertisement agency or some other company, such as an internet service provider, has easy access to behavioural data the individual should know. If an individual may be influenced by these parties, again they should be able to know. An individual should not have to master web development or have a need for advanced technical tools to find this out. While the principle of transparency is simple, permissible deviations from transparency are listed in articles 13-20 of the regulation." %>

<%= gettext "Transparency also means a right to find out when something gone wrong: if you’ve collected information about individuals which have leaked or disappeared, the individual has a right to know. This is called ”personal data breach notification” and specific rules are in article 34 of the regulation." %>

<%= gettext "Purpose limitation" %>

<%= gettext "Data collection should occur only for specific and limited purposes. These purposes should be explicit and understandable. (5(1)(b))" %>

<%= gettext "The purpose for collecting data may be interpreted broadly, and means anything from marketing to improving the web. At Dataskydd.net's Webbkoll we prefer methods of improving the web that do not include collecting data from private persons. That’s why we’ve compiled a large number of recommendations and tools which minimise data collection." %>

<%= gettext "Data minimisation" %>

<%= gettext "As little data as possible to achieve the purpose should be collected .(5(1)(c))" %>

<%= gettext "Depending on the purposes for collecting personal data, data minimisation may mean different things. Webbkoll makes it easy to find out how not to collect personal data and how not to inadvertently leak personal data. Should one want to collect personal data anyway, one needs to be transparent about such collection and one also needs to follow the rules in chapter 4 of the regulation. The rules of how to collect and process personal data are in place to ensure that anyone who chooses a purpose for data collection also reflects on the consequences of such choices." %>

<%= gettext "Accuracy" %>

<%= gettext "Personal data shall be accurate, and if they aren’t, there must be a procedure to correct them." %>

<%= gettext "This principle above all concerns information registered by public authorities or companies, for instance in the credit check industry. In web development, it is more common with ”fuzzy” data sets, and the consequences of being erroneously categorised in a given profiling operation is normally not worse than that one receives online advertisement which is not specifically targeted to ones own group." %>

<%= gettext "Storage limitation" %>

<%= gettext "Personal data should not be saved or stored longer than necessary." %>

<%= gettext "This right ties into purpose limitation and data minisation. If one follows the recommendation of Webbkoll, one does not have to concern oneself so much with this principle." %>

<%= gettext "Integrity and confidentiality" %>

<%= gettext "Data should be processed in a secure way, both organisatorially and technically." %>

<%= gettext "Webbkoll makes it easy to see which technical protection mechanisms for data protection are in place in a given website. We have identified measures which should not require large organisational changes, or increase web management costs. Most of our recommendations are simple enough to implement, and they are cost neutral. Our goal is to make it as easy as possible for individuals to exercise their rights to privacy and data protection, and also to provide web designers and managers with simple ”rules of thumb” to help individuals exercise these rights." %>

<%= gettext "Accountability" %>

<%= gettext "The one responsible for the website is responsible for adherence to these principles." %>

<%= gettext "Since responsibility can be a difficult burden, Webbkoll has a large set of recommendations for data protection which may go further than what one could be legally liable for. We want to enable the best possible data protection with the least amount of administrative burdens. One of the reasons the rules of the data protection regulation make it seem bureaucratic and boring not to data minimise, is so that each actor in society who wishes to influence others has to consider carefully the way in which they use such power." %>

<%= gettext "FAQ" %>

<%= gettext "What is data protection?" %>

<%= gettext "Data protection is a human right in the European Union. It’s a collection of administrative and formal requirements for how to collect, process and use data relating to individuals. The purpose of this protection is to provide individuals with the means necessary to exercise their right to privacy. Data protection law guarantees transparency, choice and knowledge for individuals with regards to who influences them, and under which conditions." %>

<%= gettext "In May 2018 a new law about data protection will enter into force in the European Union. It is a regulation and will apply equally in all the 28 member states." %>

<%= gettext "What is ”behavioural monitoring”?" %>

<%= gettext "Behavioural monitoring, or ”profiling”, is when someone monitors how a given person, or set of persons, typically behave. This includes monitoring whether a particular group, say young people or women of a median income, frequently visit certain deeplinks, have to look up certain vocabulary or that they end up on the website through using a particular search engine or social platform. Behavioural monitoring is used to discover what certain classes of people may be assumed to find interesting, difficult or funny." %>

<%= gettext "It is also the categorisation of individuals into these groups. Once a web visitor is stuffed into a particular category, they may be positively or negatively discriminated against because of the categorisation." %>

<%= gettext "Profiling is mostly used in the advertisement industry to decide which type of advertisements a particular individual should be exposed to. Parents of small children, or people who know parents of small children, may receive ads for nappies, prams or family vacations. Increasingly, profiling is used to determine what contents are served by newspapers. The above mentioned groups may for instance receive short articles about new-borns if they are queueing (and have little time) or longer articles about new-borns if they are on a train (and have more time)." %>

<%= gettext "Profiling may additionally be used to shape political opinions, for instance through targetting specific groups with political information, or to enact measures against groups based on their assumed characteristics. This form of political work is called ”nudging” and may also be deployed to increase acceptance of specific measures (like the construction of a public park) in specific groups (such as the individuals living near the envisaged park)." %>

<%= gettext "What do you mean by ”gossiping to third-parties”?" %>

<%= gettext "We use the word gossiping to mean that information about somebody’s behaviour, reading habits or preferences is handed over to somebody other than the actor responsible for the website." %>

<%= gettext "In modern web development, it’s become common for a website not to be run from only one location. When you visit a website, you’re not only entering into contact with those running the website, but also all the businesses and organisations which collaborate with the managers of the websites. These may be internet service providers, script providers, font providers, analytics tools providers and a range of other providers. If the manager of the websites hands over information about visitors to any of these third-parties, it is a form of gossiping since it is usually not evident to the visitors that this type of information is being handed over." %>

<%= gettext "A webstore may for instance hand over the task of profiling visitors to an advertisement agency, and a public authority may have constructed its website in a way that automatically hands over behavioural data to advertisers. Advertisers are the most common and least transparent form of third parties." %>

<%= gettext "What are the principles of the EU general data protection regulation?" %>

<%= gettext(~s|The general data protection regulation of the European Union enters into force on the 25th of May 2018 and concerns the balancing of power being those influencing individuals (typically companies and public authorities) and the individuals themselves. Webbkoll is a tool to find out who is collecting information about individuals, and what can be done to stop invisible tracking.|) |> raw %>

<%= gettext "Lawfulness, fairness and transparency" %>

<%= gettext "An individual should be able to understand the terms of interactions with others. (5(1)(a))." %>

<%= gettext "Webbkoll see lawfulness, fairness and transparency as a requirement that individuals should understand with whom they are in contact by visiting a website. If an advertisement agency or some other company, such as an internet service provider, has easy access to behavioural data the individual should know. If an individual may be influenced by these parties, again they should be able to know. An individual should not have to master web development or  have a need for advanced technical tools to find this out. While the principle of transparency is simple, permissible deviations from transparency are listed in articles 13-20 of the regulation." %>

<%= gettext "Transparency also means a right to find out when something gone wrong: if you’ve collected information about individuals which have leaked or disappeared, the individual has a right to know. This is called ”personal data breach notification” and specific rules are in article 34 of the regulation." %>

<%= gettext "Purpose limitation" %>

<%= gettext "Data collection should occur only for specific and limited purposes. These purposes should be explicit and understandable. (5(1)(b))" %>

<%= gettext "The purpose for collecting data may be interpreted broadly, and means anything from marketing to improving the web. At Dataskydd.net's Webbkoll we prefer methods of improving the web that do not include collecting data from private persons. That’s why we’ve compiled a large number of recommendations and tools which minimise data collection." %>

<%= gettext "Data minimisation" %>

<%= gettext "As little data as possible to achieve the purpose should be collected .(5(1)(c))" %>

<%= gettext "Depending on the purposes for collecting personal data, data minimisation may mean different things. Webbkoll makes it easy to find out how not to collect personal data and how not to inadvertently leak personal data. Should one want to collect personal data anyway, one needs to be transparent about such collection and one also needs to follow the rules in chapter 4 of the regulation. The rules of how to collect and process personal data are in place to ensure that anyone who chooses a purpose for data collection also reflects on the consequences of such choices." %>

<%= gettext "Accuracy" %>

<%= gettext "Personal data shall be accurate, and if they aren’t, there must be a procedure to correct them." %>

<%= gettext "This principle above all concerns information registered by public authorities or companies, for instance in the credit check industry. In web development, it is more common with ”fuzzy” data sets, and the consequences of being erroneously categorised in a given profiling operation is normally not worse than that one receives online advertisement which is not specifically targetted to ones own group." %>

<%= gettext "Storage limitation" %>

<%= gettext "Personal data should not be saved or stored longer than necessary." %>

<%= gettext "This right ties into purpose limitation and data minisation. If one follows the recommendation of Webbkoll, one does not have to concern oneself so much with this principle." %>

<%= gettext "Integrity and confidentiality" %>

<%= gettext "Data should be processed in a secure way, both organisatorially and technically." %>

<%= gettext "Webbkoll makes it easy to see which technical protection mechanisms for data protection are in place in a given website. We have identified measures which should not require large organisational changes, or increase web management costs. Most of our recommendations are simple enough to implement, and they are cost neutral. Our goal is to make it as easy as possible for individuals to exercise their rights to privacy and data protection, and also to provide web designers and managers with simple ”rules of thumb” to help individuals exercise these rights." %>

<%= gettext "Accountability" %>

<%= gettext "The one responsible for the website is responsible for adherence to these principles." %>

<%= gettext "Since responsibility can be a difficult burden, Webbkoll has a large set of recommendations for data protection which may go further than what one could be legally liable for. We want to enable the best possible data protection with the least amount of administrative burdens. One of the reasons the rules of the data protection regulation make it seem bureaucratic and boring not to data minimise, is so that each actor in society who wishes to influence others has to consider carefully the way in which they use such power." %>


Update email year 2017 -> 2018

Update email year 2017 -> 2018

      <%= render @view_module, @view_template, assigns %>

Our amazing partners and sponsors

          © Make or Break 2018

      <%= render @view_module, @view_template, assigns %>

Our amazing partners and sponsors

          © Make or Break 2017


fix bug with year page

fix bug with year page

<%
 cond do
    assigns[:page_type] == :post ->
      blog_feature_image = @post.feature_image || @blog_feature_image
      title =@post.title
      description = @post.description
    assigns[:page_type] == :page ->
      blog_feature_image = @page.feature_image || @blog_feature_image
      title =@page.title
      description = @page.description
    assigns[:page_type] == :tag ->
      blog_feature_image = @blog_feature_image
      title = "Viewing posts with tag " <> @tag
      description = @blog_title
    assigns[:page_type] == :year ->
      blog_feature_image = @blog_feature_image
      title = "Viewing posts for the year " <> Integer.to_string(@year)
      description = @blog_title
    assigns[:page_type] == :month ->
      month = String.rjust(Integer.to_string(@month), 2, ?0)
      blog_feature_image = @blog_feature_image
      title = "Viewing posts for the month" <> Integer.to_string(@year) <> "-" <> month
      description = @blog_title
    true ->
      blog_feature_image = @blog_feature_image
      title = @blog_title
      description = @blog_headline
  end
%>

<meta property="og:title" content="<%= title %>"/>
<meta property="og:image" content="<%= static_url(@conn, blog_feature_image) %>"/>
<meta property="og:image:secure_url" content="<%= static_url(@conn, blog_feature_image) %>"/>
<meta property="og:description" content="<%= description %>"/>
<meta name="description" content="<%= description %>">

<%
 cond do
    assigns[:page_type] == :post ->
      blog_feature_image = @post.feature_image || @blog_feature_image
      title =@post.title
      description = @post.description
    assigns[:page_type] == :page ->
      blog_feature_image = @page.feature_image || @blog_feature_image
      title =@page.title
      description = @page.description
    assigns[:page_type] == :tag ->
      blog_feature_image = @blog_feature_image
      title = "Viewing posts with tag " <> @tag
      description = @blog_title
    assigns[:page_type] == :year ->
      blog_feature_image = @blog_feature_image
      title = "Viewing posts for the year " <> @year
      description = @blog_title
    assigns[:page_type] == :month ->
      month = String.rjust(Integer.to_string(@month), 2, ?0)
      blog_feature_image = @blog_feature_image
      title = "Viewing posts for the month" <> @year <> "-" <> month
      description = @blog_title
    true ->
      blog_feature_image = @blog_feature_image
      title = @blog_title
      description = @blog_headline
  end
%>

<meta property="og:title" content="<%= title %>"/>
<meta property="og:image" content="<%= static_url(@conn, blog_feature_image) %>"/>
<meta property="og:image:secure_url" content="<%= static_url(@conn, blog_feature_image) %>"/>
<meta property="og:description" content="<%= description %>"/>
<meta name="description" content="<%= description %>">


Header

Header

  <%= for post <- @posts do %>

  <% img_src = hd(post.json_metadata["image"] || post.json_metadata["images"] || [false] ) %>

      <a href="/authors/<%= post.author %>/<%= post.permlink %>">

        <%= if img_src do %>
          <img src="<%= img_src %>">
        <% end %>

        <a class="header" href="/authors/<%= post.author %>/<%= post.permlink %>"> <%= post.title %>

        <a class="ui large blue ribbon label" href="/authors/<%= post.author %>">  @<%= post.author  %>

          <%= for tag <- post.tags do %>
          <a class="ui  label" href="/tags/<%=tag%>">
            <%= format_tag(tag, @conn.assigns.lang) %>

          <% end %>

    <% end %>

      <%= for {v, i} <- generate_pagination_list(@current_page) do %>

      <a class="<%=if v == @current_page, do: "active" %> item"
        href="<%= @conn.request_path <> "?" <> URI.encode_query(%{"page"=> v}) %>">
        <%= v %>

      <% end %>

Tags present in this page

      <%= for post <- @posts do %>
          <%= for tag <- post.tags do %>
          <a class="ui Small label" href="/tags/<%=tag%>">
            <%= format_tag(tag, @conn.assigns.lang) %>

          <% end %>
      <% end %>

  <%= for post <- @posts do %>

  <% img_src = hd(post.json_metadata["image"] || post.json_metadata["images"] || [false] ) %>

      <a href="/authors/<%= post.author %>/<%= post.permlink %>">

        <%= if img_src do %>
          <img src="<%= img_src %>">
        <% end %>

        <a class="header" href="/authors/<%= post.author %>/<%= post.permlink %>"> <%= post.title %>

        <a class="ui large blue ribbon label" href="/authors/<%= post.author %>">  @<%= post.author  %>

          <%= for tag <- post.tags do %>
          <a class="ui  label" href="/tags/<%=tag%>">
            <%= format_tag(tag, @conn.assigns.lang) %>

          <% end %>

    <% end %>

      <%= for {v, i} <- generate_pagination_list(@current_page) do %>

      <a class="<%=if v == @current_page, do: "active" %> item"
        href="<%= @conn.request_path <> "?" <> URI.encode_query(%{"page"=> v}) %>">
        <%= v %>

      <% end %>

      <%= for post <- @posts do %>
          <%= for tag <- post.tags do %>
          <a class="ui Small label" href="/tags/<%=tag%>">
            <%= format_tag(tag, @conn.assigns.lang) %>

          <% end %>
      <% end %>


Update html footer

Update html footer

Directory listing generated by plug_static_ls


more stats links

more stats links

      <%= link [fa_icon("folder-o"), " ", "Panoptikum"],
               to: category_frontend_path(@conn, :stats) %>
      /
      <%= if @category.parent do %>
        <%= link [fa_icon("folder-o"), " ", @category.parent.title],
                 to: category_frontend_path(@conn, :show_stats, @category.parent) %>
        /
      <% end %>
      <%= fa_icon("folder-open-o") %> <%= @category.title %>

    <%= if @category.children != [] do %>
      <%= for group <- Enum.chunk(@category.children, 6, 6, []) do %>

          <%= for subcategory <- group do %>

              <%= link [fa_icon("folder-o"), " ", subcategory.title],
                       to: category_frontend_path(@conn, :show_stats, subcategory),
                       class: "btn btn-xs btn-light-gray truncate" %>

          <% end %>

      <% end %>

    <% end %>

    Jump to:
    <%= for {language, podcasts} <- Enum.group_by(@podcasts, &Map.get(&1, :language_name)) do %>

      <%= List.first(podcasts) && List.first(podcasts).language_emoji %>
      <%= link ( language || "Language unknown"), to: "#" <> (language || "Language unknown"),
                                                  id: "lang-#{language}"%>
    <% end %>

    <%= for {language, podcasts} <- Enum.group_by(@podcasts, &Map.get(&1, :language_name)) do %>
      <h3 id="<%= language %>"><%= List.first(podcasts) && List.first(podcasts).language_emoji %>
        <%= language || "Language unknown" %>

      <%= for group <- Enum.chunk(podcasts, 6, 6, []) do %>

          <%= for podcast <- group do %>

                <%= link [fa_icon("podcast"), " ", podcast.title],
                         to: podcast_frontend_path(@conn, :show, podcast.id),
                         class: "btn btn-default btn-xs truncate",
                         id: "podcast-#{podcast.id}" %>

          <% end %>

      <% end %>
    <% end %>

<%= if @current_user do %>
  <%= like_or_unlike(@current_user.id, @category.id) %>
  <%= follow_or_unfollow(@current_user.id, @category.id) %>
<% end %>

      <%= link [fa_icon("folder-o"), " ", "Panoptikum"],
               to: category_frontend_path(@conn, :index_stats) %>
      /
      <%= if @category.parent do %>
        <%= link [fa_icon("folder-o"), " ", @category.parent.title],
                 to: category_frontend_path(@conn, :show_stats, @category.parent) %>
        /
      <% end %>
      <%= fa_icon("folder-open-o") %> <%= @category.title %>

    <%= if @category.children != [] do %>
      <%= for group <- Enum.chunk(@category.children, 6, 6, []) do %>

          <%= for subcategory <- group do %>

              <%= link [fa_icon("folder-o"), " ", subcategory.title],
                       to: category_frontend_path(@conn, :show_stats, subcategory),
                       class: "btn btn-xs btn-light-gray truncate" %>

          <% end %>

      <% end %>

    <% end %>

    Jump to:
    <%= for {language, podcasts} <- Enum.group_by(@podcasts, &Map.get(&1, :language_name)) do %>

      <%= List.first(podcasts) && List.first(podcasts).language_emoji %>
      <%= link ( language || "Language unknown"), to: "#" <> (language || "Language unknown"),
                                                  id: "lang-#{language}"%>
    <% end %>

    <%= for {language, podcasts} <- Enum.group_by(@podcasts, &Map.get(&1, :language_name)) do %>
      <h3 id="<%= language %>"><%= List.first(podcasts) && List.first(podcasts).language_emoji %>
        <%= language || "Language unknown" %>

      <%= for group <- Enum.chunk(podcasts, 6, 6, []) do %>

          <%= for podcast <- group do %>

                <%= link [fa_icon("podcast"), " ", podcast.title],
                         to: podcast_frontend_path(@conn, :show, podcast.id),
                         class: "btn btn-default btn-xs truncate",
                         id: "podcast-#{podcast.id}" %>

          <% end %>

      <% end %>
    <% end %>

<%= if @current_user do %>
  <%= like_or_unlike(@current_user.id, @category.id) %>
  <%= follow_or_unfollow(@current_user.id, @category.id) %>
<% end %>


Convert text input to textarea

Convert text input to textarea

<%= form_for @changeset, post_path(@conn, :create), fn f -> %>

      <%= label f, :title %>
      <%= error_tag f, :title %>

      <%= text_input f, :title, placeholder: "Enter title..." %>

      <%= label f, :body %>
      <%= error_tag f, :body %>

      <%= textarea f, :body,
        placeholder: "Enter body...",
        class: "autosize",
        style: "overflow: hidden; word-wrap: break-word; height: 72px;"
      %>

      <%= label f, :channel_id, "Channel" %>
      <%= error_tag f, :channel_id %>

      <%= select f, :channel_id, @channels, prompt: "" %>

  <%= submit "Submit" %>
  <%= link("cancel", to: "/") %>
<% end %>

<%= form_for @changeset, post_path(@conn, :create), fn f -> %>

      <%= label f, :title %>
      <%= error_tag f, :title %>

      <%= text_input f, :title, placeholder: "Enter title..." %>

      <%= label f, :body %>
      <%= error_tag f, :body %>

      <%= text_input f, :body, placeholder: "Enter body..." %>

      <%= label f, :channel_id, "Channel" %>
      <%= error_tag f, :channel_id %>

      <%= select f, :channel_id, @channels, prompt: "" %>

  <%= submit "Submit" %>
  <%= link("cancel", to: "/") %>
<% end %>


tiny change

tiny change

<a href="https://steemit.com/@<%= @post.author %>/<%= @post.permlink %>"><%= @post.title %>

Author: <a href="https://beyondboinc.net/authors/<%= @post.author %>/"><%= @post.author %>

Tags:
          <%= for tag <- @post.tags do %>
          <a class="ui  label" href="/tags/<%=tag%>">
            <%= format_tag(tag, @conn.assigns.lang) %>

          <% end %>

        <%= raw(@post.body) %>

		  Home
		  /

@<a href="https://beyondboinc.net/authors/<%= @post.author %>/"><%= @post.author %>

		  /

<a href="https://beyondboinc.net/authors/<%= @post.author %>/<%= @post.permlink %>/"><%= @post.title %>

<a href="https://steemit.com/@<%= @post.author %>/<%= @post.permlink %>"><%= @post.title %>

Author: <a href="https://beyondboinc.net/authors/<%= @post.author %>/"><%= @post.author %>

Tags:
          <%= for tag <- @post.tags do %>
          <a class="ui  label" href="/tags/<%=tag%>">
            <%= format_tag(tag, @conn.assigns.lang) %>

          <% end %>

        <%= raw(@post.body) %>

		  Home
		  /

Author: <a href="https://beyondboinc.net/authors/<%= @post.author %>/"><%= @post.author %>

		  /

<a href="https://beyondboinc.net/authors/<%= @post.author %>/<%= @post.permlink %>/"><%= @post.permlink %>


rustler_mix: Drop lazy_static from template

The dependency is not needed to be mentioned explicitly anymore.

[package]
name = "<%= library_name %>"
version = "0.1.0"
authors = []
edition = "2018"

[lib]
name = "<%= library_name %>"
path = "src/lib.rs"
crate-type = ["dylib"]

[dependencies]
rustler = "<%= rustler_version %>"
lazy_static = "1.0"


Fixes logout behavior

Fixes logout behavior

Überauth + Phoenix Example

  This is an application to show an example of how to wire up
  Überauth with
  Phoenix.

  <%= if @current_user do %>

Welcome, <%= @current_user.name %>!

    <img src="<%= @current_user.avatar %>" class="img-circle"/>
    <%= button "Logout", to: auth_path(@conn, :delete), method: :delete, class: "btn btn-danger" %>

  <% else %>

      Sign in with GitHub

      Sign in with Facebook

      Sign in with Google

      Sign in with Slack

      Sign in with Twitter

      Sign in with Username/Password

  <% end %>

Überauth + Phoenix Example

  This is an application to show an example of how to wire up
  Überauth with
  Phoenix.

  <%= if @current_user do %>

Welcome, <%= @current_user.name %>!

    <img src="<%= @current_user.avatar %>" class="img-circle"/>
    <%= link "Logout", to: auth_path(@conn, :delete), method: :delete, class: "btn btn-danger" %>

  <% else %>

      Sign in with GitHub

      Sign in with Facebook

      Sign in with Google

      Sign in with Slack

      Sign in with Twitter

      Sign in with Username/Password

  <% end %>


Use working git sha example

Use working git sha example

# This file excludes paths from the Docker build context.
#
# By default, Docker's build context includes all files (and folders) in the
# current directory. Even if a file isn't copied into the container it is still sent to
# the Docker daemon.
#
# There are multiple reasons to exclude files from the build context:
#
# 1. Prevent nested folders from being copied into the container (ex: exclude
#    /assets/node_modules when copying /assets)
# 2. Reduce the size of the build context and improve build time (ex. /build, /deps, /doc)
# 3. Avoid sending files containing sensitive information
#
# More information on using .dockerignore is available here:
# https://docs.docker.com/engine/reference/builder/#dockerignore-file

.dockerignore

# Ignore git, but keep git HEAD and refs to access current commit hash if needed:
#
$ cat .git/HEAD | awk '{print ".git/"$2}' | xargs cat
# d0b8727759e1e0e7aa3d41707d12376e373d5ecc
.git
!.git/HEAD
!.git/refs

# Common development/test artifacts
/cover/
/doc/
/test/
/tmp/
.elixir_ls

# Mix artifacts
/_build/
/deps/
*.ez

# Generated on crash by the VM
erl_crash.dump

# Static artifacts - These should be fetched and built inside the Docker image
/assets/node_modules/
/priv/static/assets/
/priv/static/cache_manifest.json

# This file excludes paths from the Docker build context.
#
# By default, Docker's build context includes all files (and folders) in the
# current directory. Even if a file isn't copied into the container it is still sent to
# the Docker daemon.
#
# There are multiple reasons to exclude files from the build context:
#
# 1. Prevent nested folders from being copied into the container (ex: exclude
#    /assets/node_modules when copying /assets)
# 2. Reduce the size of the build context and improve build time (ex. /build, /deps, /doc)
# 3. Avoid sending files containing sensitive information
#
# More information on using .dockerignore is available here:
# https://docs.docker.com/engine/reference/builder/#dockerignore-file

.dockerignore

# Ignore git, but keep git HEAD and refs to access current commit hash if needed:
#
# $ git show HEAD --pretty=full | head -n 1
# commit d0b8727759e1e0e7aa3d41707d12376e373d5ecc
.git
!.git/HEAD
!.git/refs

# Common development/test artifacts
/cover/
/doc/
/test/
/tmp/
.elixir_ls

# Mix artifacts
/_build/
/deps/
*.ez

# Generated on crash by the VM
erl_crash.dump

# Static artifacts - These should be fetched and built inside the Docker image
/assets/node_modules/
/priv/static/assets/
/priv/static/cache_manifest.json