<commit_before>(() => {
  const isDev = location.hostname === 'localhost';
  const isNext = location.hostname === 'next.shoelace.style';
  const customElements = fetch('/dist/custom-elements.json')
    .then(res => res.json())
    .catch(err => console.error(err));

  function createPropsTable(props) {
    const table = document.createElement('table');
    table.innerHTML = `

          Name
          Description
          Reflects
          Type
          Default

        ${props
          .map(prop => {
            const hasAttribute = !!prop.attribute;
            const isAttributeDifferent = prop.attribute !== prop.name;
            let attributeInfo = '';

            if (!hasAttribute) {
              attributeInfo = `<br><small>(property only)</small>`;
            } else if (isAttributeDifferent) {
              attributeInfo = `

                <sl-tooltip content="This attribute is different than the property">

                      ${escapeHtml(prop.attribute)}

                </sl-tooltip>`;
            }

            return `

                  ${escapeHtml(prop.name)}
                  ${attributeInfo}

                  ${escapeHtml(prop.description)}

                ${
                  prop.reflects ? '<sl-icon label="yes" name="check"></sl-icon>' : ''
                }
                ${prop.type?.text ? `<code>${escapeHtml(prop.type?.text || '')}</code>` : '-'}
                ${prop.default ? `<code>${escapeHtml(prop.default)}</code>` : '-'}

            `;
          })
          .join('')}

    `;

    return table.outerHTML;
  }

  function createEventsTable(events) {
    const table = document.createElement('table');
    table.innerHTML = `

          Name
          React Event
          Description
          Event Detail

        ${events
          .map(
            event => `

                ${escapeHtml(event.name)}
                ${escapeHtml(event.reactName)}
                ${escapeHtml(event.description)}
                ${event.type?.text ? `<code>${escapeHtml(event.type?.text)}` : '-'}

            `
          )
          .join('')}

    `;

    return table.outerHTML;
  }

  function createMethodsTable(methods) {
    const table = document.createElement('table');
    table.innerHTML = `

          Name
          Description
          Arguments

        ${methods
          .map(
            method => `

                ${escapeHtml(method.name)}
                ${escapeHtml(method.description)}

                  ${
                    method.parameters?.length
                      ? `
                        ${escapeHtml(
                          method.parameters.map(param => `${param.name}: ${param.type.text}`).join(', ')
                        )}
                      `
                      : '-'
                  }

           `
          )
          .join('')}

    `;

    return table.outerHTML;
  }

  function createSlotsTable(slots) {
    const table = document.createElement('table');
    table.innerHTML = `

          Name
          Description

        ${slots
          .map(
            slot => `

                ${slot.name ? `<code>${escapeHtml(slot.name)}</code>` : '(default)'}
                ${escapeHtml(slot.description)}

            `
          )
          .join('')}

    `;

    return table.outerHTML;
  }

  function createCustomPropertiesTable(styles) {
    const table = document.createElement('table');
    table.innerHTML = `

          Name
          Description

        ${styles
          .map(
            style => `

                ${escapeHtml(style.name)}
                ${escapeHtml(style.description)}

            `
          )
          .join('')}

    `;

    return table.outerHTML;
  }

  function createPartsTable(parts) {
    const table = document.createElement('table');
    table.innerHTML = `

          Name
          Description

        ${parts
          .map(
            part => `

                ${escapeHtml(part.name)}
                ${escapeHtml(part.description)}

           `
          )
          .join('')}

    `;

    return table.outerHTML;
  }

  function createAnimationsTable(animations) {
    const table = document.createElement('table');
    table.innerHTML = `

          Name
          Description

        ${animations
          .map(
            animation => `

                ${escapeHtml(animation.name)}
                ${escapeHtml(animation.description)}

            `
          )
          .join('')}

    `;

    return table.outerHTML;
  }

  function createDependenciesList(targetComponent, allComponents) {
    const ul = document.createElement('ul');
    const dependencies = [];

    // Recursively fetch subdependencies
    function getDependencies(tag) {
      const component = allComponents.find(c => c.tagName === tag);
      if (!component || !Array.isArray(component.dependencies)) {
        return [];
      }

      component.dependencies?.map(tag => {
        if (!dependencies.includes(tag)) {
          dependencies.push(tag);
        }
        getDependencies(tag);
      });
    }

    getDependencies(targetComponent);
    dependencies.sort().map(tag => {
      const li = document.createElement('li');
      li.innerHTML = `<code><${tag}></code>`;
      ul.appendChild(li);
    });

    return ul.outerHTML;
  }

  function escapeHtml(html) {
    return (html + '')
      .replace(/&/g, '&')
      .replace(/</g, '<')
      .replace(/>/g, '>')
      .replace(/"/g, '"')
      .replace(/'/g, ''')
      .replace(/`(.*?)`/g, '$1');
  }

  function getAllComponents(metadata) {
    const allComponents = [];
    metadata.modules?.map(module => {
      module.declarations?.map(declaration => {
        if (declaration.customElement) {
          // Generate the dist path based on the src path and attach it to the component
          declaration.path = module.path.replace(/^src\//, 'dist/').replace(/\.ts$/, '.js');

          allComponents.push(declaration);
        }
      });
    });

    return allComponents;
  }

  function getComponent(metadata, tagName) {
    return getAllComponents(metadata).find(component => component.tagName === tagName);
  }

  if (!window.$docsify) {
    throw new Error('Docsify must be loaded before installing this plugin.');
  }

  window.$docsify.plugins.push((hook, vm) => {
    hook.mounted(async function () {
      const metadata = await customElements;
      const target = document.querySelector('.app-name');

      // Add version
      const version = document.createElement('div');
      version.classList.add('sidebar-version');
      version.textContent = isDev ? 'Development' : isNext ? 'Next' : metadata.package.version;
      target.appendChild(version);

      // Store version for reuse
      sessionStorage.setItem('sl-version', metadata.package.version);

      // Add repo buttons
      const buttons = document.createElement('div');
      buttons.classList.add('sidebar-buttons');
      buttons.innerHTML = `
        <sl-button size="small" class="repo-button repo-button--sponsor" href="https://github.com/sponsors/claviska" target="_blank">
          <sl-icon slot="prefix" name="heart"></sl-icon> Sponsor
        </sl-button>
        <sl-button size="small" class="repo-button repo-button--github" href="https://github.com/shoelace-style/shoelace/stargazers" target="_blank">
          <sl-icon slot="prefix" name="github"></sl-icon> Star
        </sl-button>
        <sl-button size="small" class="repo-button repo-button--twitter" href="https://twitter.com/shoelace_style" target="_blank">
          <sl-icon slot="prefix" name="twitter"></sl-icon> Follow
        </sl-button>
      `;
      target.appendChild(buttons);
    });

    hook.beforeEach(async function (content, next) {
      const metadata = await customElements;

      // Replace %VERSION% placeholders
      content = content.replace(/%VERSION%/g, metadata.package.version);

      // Handle [component-header] tags
      content = content.replace(/\[component-header:([a-z-]+)\]/g, (match, tag) => {
        const component = getComponent(metadata, tag);
        let result = '';

        if (!component) {
          console.error('Component not found in metadata: ' + tag);
          return next(content);
        }

        let badgeType = 'neutral';
        if (component.status === 'stable') badgeType = 'primary';
        if (component.status === 'experimental') badgeType = 'warning';
        if (component.status === 'planned') badgeType = 'neutral';
        if (component.status === 'deprecated') badgeType = 'danger';

        result += `

              <${component.tagName}> | ${component.name}

              <sl-badge variant="neutral" pill>
                Since ${component.since || '?'}
              </sl-badge>

              <sl-badge variant="${badgeType}" pill style="text-transform: capitalize;">
                ${component.status}
              </sl-badge>

        `;

        return result.replace(/^ +| +$/gm, '');
      });

      // Handle [component-metadata] tags
      content = content.replace(/\[component-metadata:([a-z-]+)\]/g, (match, tag) => {
        const component = getComponent(metadata, tag);
        let result = '';

        if (!component) {
          console.error('Component not found in metadata: ' + tag);
          return next(content);
        }

        // Remove members that are private or don't have a description
        const members = component.members?.filter(member => member.description && member.privacy !== 'private');
        const methods = members?.filter(prop => prop.kind === 'method' && prop.privacy !== 'private');
        const props = members?.filter(prop => {
          // Look for a corresponding attribute
          const attribute = component.attributes?.find(attr => attr.fieldName === prop.name);
          if (attribute) {
            prop.attribute = attribute.name || attribute.fieldName;
          }

          return prop.kind === 'field' && prop.privacy !== 'private';
        });

        if (component.path) {
          /* prettier-ignore */
          result += `
            ## Importing

            <sl-tab-group>
            <sl-tab slot="nav" panel="script">Script</sl-tab>
            <sl-tab slot="nav" panel="import">Import</sl-tab>
            <sl-tab slot="nav" panel="bundler">Bundler</sl-tab>
            <sl-tab slot="nav" panel="react">React</sl-tab>

            <sl-tab-panel name="script">\n
            To import this component from [the CDN](https://www.jsdelivr.com/package/npm/@shoelace-style/shoelace) using a script tag:

            \`\`\`html

            \`\`\`
            </sl-tab-panel>

            <sl-tab-panel name="import">\n
            To import this component from [the CDN](https://www.jsdelivr.com/package/npm/@shoelace-style/shoelace) using a JavaScript import:

            \`\`\`js
            import 'https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@${metadata.package.version}/${component.path}';
            \`\`\`
            </sl-tab-panel>

            <sl-tab-panel name="bundler">\n
            To import this component using [a bundler](/getting-started/installation#bundling):
            \`\`\`js
            import '@shoelace-style/shoelace/${component.path}';
            \`\`\`
            </sl-tab-panel>

            <sl-tab-panel name="react">\n
            To import this component as a [React component](/frameworks/react):
            \`\`\`js
            import { ${component.name} } from '@shoelace-style/shoelace/dist/react';
            \`\`\`
            </sl-tab-panel>
            </sl-tab-group>
          `;
        }

        if (props?.length) {
          result += `
            ## Properties
            ${createPropsTable(props)}
          `;
        }

        if (component.events?.length) {
          result += `
            ## Events
            ${createEventsTable(component.events)}
          `;
        }

        if (methods?.length) {
          result += `
            ## Methods

              Methods can be called by obtaining a reference to the element and calling
              el.methodName().

              Methods can be called by obtaining a ref to the element and calling
              ref.current.methodName().

            ${createMethodsTable(methods)}
          `;
        }

        if (component.slots?.length) {
          result += `
            ## Slots
            ${createSlotsTable(component.slots)}
          `;
        }

        if (component.cssProperties?.length) {
          result += `
            ## CSS Custom Properties
            ${createCustomPropertiesTable(component.cssProperties)}
          `;
        }

        if (component.cssParts?.length) {
          result += `
            ## CSS Parts
            ${createPartsTable(component.cssParts)}
          `;
        }

        if (component.animations?.length) {
          result += `
            ## Animations
            ${createAnimationsTable(component.animations)}

            Learn how to [customize animations](/getting-started/customizing#animations).
          `;
        }

        if (component.dependencies?.length) {
          result += `
            ## Dependencies

            This component imports the following dependencies.

            ${createDependenciesList(component.tagName, getAllComponents(metadata))}
          `;
        }

        // Strip whitespace so markdown doesn't process things as code blocks
        return result.replace(/^ +| +$/gm, '');
      });

      next(content);
    });

    // Wrap tables so we can scroll them horizontally when needed
    hook.doneEach(function () {
      const content = document.querySelector('.content');
      const tables = [...content.querySelectorAll('table')];

      tables.map(table => {
        table.outerHTML = `

            ${table.outerHTML}

        `;
      });
    });
  });
})();
<commit_msg>show defaults<commit_after>(() => {
  const isDev = location.hostname === 'localhost';
  const isNext = location.hostname === 'next.shoelace.style';
  const customElements = fetch('/dist/custom-elements.json')
    .then(res => res.json())
    .catch(err => console.error(err));

  function createPropsTable(props) {
    const table = document.createElement('table');
    table.innerHTML = `

          Name
          Description
          Reflects
          Type
          Default

        ${props
          .map(prop => {
            const hasAttribute = !!prop.attribute;
            const isAttributeDifferent = prop.attribute !== prop.name;
            let attributeInfo = '';

            if (!hasAttribute) {
              attributeInfo = `<br><small>(property only)</small>`;
            } else if (isAttributeDifferent) {
              attributeInfo = `

                <sl-tooltip content="This attribute is different than the property">

                      ${escapeHtml(prop.attribute)}

                </sl-tooltip>`;
            }

            return `

                  ${escapeHtml(prop.name)}
                  ${attributeInfo}

                  ${escapeHtml(prop.description)}

                ${
                  prop.reflects ? '<sl-icon label="yes" name="check"></sl-icon>' : ''
                }
                ${prop.type?.text ? `<code>${escapeHtml(prop.type?.text || '')}</code>` : '-'}
                ${prop.default ? `<code>${escapeHtml(prop.default)}</code>` : '-'}

            `;
          })
          .join('')}

    `;

    return table.outerHTML;
  }

  function createEventsTable(events) {
    const table = document.createElement('table');
    table.innerHTML = `

          Name
          React Event
          Description
          Event Detail

        ${events
          .map(
            event => `

                ${escapeHtml(event.name)}
                ${escapeHtml(event.reactName)}
                ${escapeHtml(event.description)}
                ${event.type?.text ? `<code>${escapeHtml(event.type?.text)}` : '-'}

            `
          )
          .join('')}

    `;

    return table.outerHTML;
  }

  function createMethodsTable(methods) {
    const table = document.createElement('table');
    table.innerHTML = `

          Name
          Description
          Arguments

        ${methods
          .map(
            method => `

                ${escapeHtml(method.name)}
                ${escapeHtml(method.description)}

                  ${
                    method.parameters?.length
                      ? `
                        ${escapeHtml(
                          method.parameters.map(param => `${param.name}: ${param.type.text}`).join(', ')
                        )}
                      `
                      : '-'
                  }

           `
          )
          .join('')}

    `;

    return table.outerHTML;
  }

  function createSlotsTable(slots) {
    const table = document.createElement('table');
    table.innerHTML = `

          Name
          Description

        ${slots
          .map(
            slot => `

                ${slot.name ? `<code>${escapeHtml(slot.name)}</code>` : '(default)'}
                ${escapeHtml(slot.description)}

            `
          )
          .join('')}

    `;

    return table.outerHTML;
  }

  function createCustomPropertiesTable(styles) {
    const table = document.createElement('table');
    table.innerHTML = `

          Name
          Description
          Default

        ${styles
          .map(
            style => `

                ${escapeHtml(style.name)}
                ${escapeHtml(style.description)}
                ${escapeHtml(style.default)}

            `
          )
          .join('')}

    `;

    return table.outerHTML;
  }

  function createPartsTable(parts) {
    const table = document.createElement('table');
    table.innerHTML = `

          Name
          Description

        ${parts
          .map(
            part => `

                ${escapeHtml(part.name)}
                ${escapeHtml(part.description)}

           `
          )
          .join('')}

    `;

    return table.outerHTML;
  }

  function createAnimationsTable(animations) {
    const table = document.createElement('table');
    table.innerHTML = `

          Name
          Description

        ${animations
          .map(
            animation => `

                ${escapeHtml(animation.name)}
                ${escapeHtml(animation.description)}

            `
          )
          .join('')}

    `;

    return table.outerHTML;
  }

  function createDependenciesList(targetComponent, allComponents) {
    const ul = document.createElement('ul');
    const dependencies = [];

    // Recursively fetch subdependencies
    function getDependencies(tag) {
      const component = allComponents.find(c => c.tagName === tag);
      if (!component || !Array.isArray(component.dependencies)) {
        return [];
      }

      component.dependencies?.map(tag => {
        if (!dependencies.includes(tag)) {
          dependencies.push(tag);
        }
        getDependencies(tag);
      });
    }

    getDependencies(targetComponent);
    dependencies.sort().map(tag => {
      const li = document.createElement('li');
      li.innerHTML = `<code><${tag}></code>`;
      ul.appendChild(li);
    });

    return ul.outerHTML;
  }

  function escapeHtml(html) {
    return (html + '')
      .replace(/&/g, '&')
      .replace(/</g, '<')
      .replace(/>/g, '>')
      .replace(/"/g, '"')
      .replace(/'/g, ''')
      .replace(/`(.*?)`/g, '$1');
  }

  function getAllComponents(metadata) {
    const allComponents = [];
    metadata.modules?.map(module => {
      module.declarations?.map(declaration => {
        if (declaration.customElement) {
          // Generate the dist path based on the src path and attach it to the component
          declaration.path = module.path.replace(/^src\//, 'dist/').replace(/\.ts$/, '.js');

          allComponents.push(declaration);
        }
      });
    });

    return allComponents;
  }

  function getComponent(metadata, tagName) {
    return getAllComponents(metadata).find(component => component.tagName === tagName);
  }

  if (!window.$docsify) {
    throw new Error('Docsify must be loaded before installing this plugin.');
  }

  window.$docsify.plugins.push((hook, vm) => {
    hook.mounted(async function () {
      const metadata = await customElements;
      const target = document.querySelector('.app-name');

      // Add version
      const version = document.createElement('div');
      version.classList.add('sidebar-version');
      version.textContent = isDev ? 'Development' : isNext ? 'Next' : metadata.package.version;
      target.appendChild(version);

      // Store version for reuse
      sessionStorage.setItem('sl-version', metadata.package.version);

      // Add repo buttons
      const buttons = document.createElement('div');
      buttons.classList.add('sidebar-buttons');
      buttons.innerHTML = `
        <sl-button size="small" class="repo-button repo-button--sponsor" href="https://github.com/sponsors/claviska" target="_blank">
          <sl-icon slot="prefix" name="heart"></sl-icon> Sponsor
        </sl-button>
        <sl-button size="small" class="repo-button repo-button--github" href="https://github.com/shoelace-style/shoelace/stargazers" target="_blank">
          <sl-icon slot="prefix" name="github"></sl-icon> Star
        </sl-button>
        <sl-button size="small" class="repo-button repo-button--twitter" href="https://twitter.com/shoelace_style" target="_blank">
          <sl-icon slot="prefix" name="twitter"></sl-icon> Follow
        </sl-button>
      `;
      target.appendChild(buttons);
    });

    hook.beforeEach(async function (content, next) {
      const metadata = await customElements;

      // Replace %VERSION% placeholders
      content = content.replace(/%VERSION%/g, metadata.package.version);

      // Handle [component-header] tags
      content = content.replace(/\[component-header:([a-z-]+)\]/g, (match, tag) => {
        const component = getComponent(metadata, tag);
        let result = '';

        if (!component) {
          console.error('Component not found in metadata: ' + tag);
          return next(content);
        }

        let badgeType = 'neutral';
        if (component.status === 'stable') badgeType = 'primary';
        if (component.status === 'experimental') badgeType = 'warning';
        if (component.status === 'planned') badgeType = 'neutral';
        if (component.status === 'deprecated') badgeType = 'danger';

        result += `

              <${component.tagName}> | ${component.name}

              <sl-badge variant="neutral" pill>
                Since ${component.since || '?'}
              </sl-badge>

              <sl-badge variant="${badgeType}" pill style="text-transform: capitalize;">
                ${component.status}
              </sl-badge>

        `;

        return result.replace(/^ +| +$/gm, '');
      });

      // Handle [component-metadata] tags
      content = content.replace(/\[component-metadata:([a-z-]+)\]/g, (match, tag) => {
        const component = getComponent(metadata, tag);
        let result = '';

        if (!component) {
          console.error('Component not found in metadata: ' + tag);
          return next(content);
        }

        // Remove members that are private or don't have a description
        const members = component.members?.filter(member => member.description && member.privacy !== 'private');
        const methods = members?.filter(prop => prop.kind === 'method' && prop.privacy !== 'private');
        const props = members?.filter(prop => {
          // Look for a corresponding attribute
          const attribute = component.attributes?.find(attr => attr.fieldName === prop.name);
          if (attribute) {
            prop.attribute = attribute.name || attribute.fieldName;
          }

          return prop.kind === 'field' && prop.privacy !== 'private';
        });

        if (component.path) {
          /* prettier-ignore */
          result += `
            ## Importing

            <sl-tab-group>
            <sl-tab slot="nav" panel="script">Script</sl-tab>
            <sl-tab slot="nav" panel="import">Import</sl-tab>
            <sl-tab slot="nav" panel="bundler">Bundler</sl-tab>
            <sl-tab slot="nav" panel="react">React</sl-tab>

            <sl-tab-panel name="script">\n
            To import this component from [the CDN](https://www.jsdelivr.com/package/npm/@shoelace-style/shoelace) using a script tag:

            \`\`\`html

            \`\`\`
            </sl-tab-panel>

            <sl-tab-panel name="import">\n
            To import this component from [the CDN](https://www.jsdelivr.com/package/npm/@shoelace-style/shoelace) using a JavaScript import:

            \`\`\`js
            import 'https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@${metadata.package.version}/${component.path}';
            \`\`\`
            </sl-tab-panel>

            <sl-tab-panel name="bundler">\n
            To import this component using [a bundler](/getting-started/installation#bundling):
            \`\`\`js
            import '@shoelace-style/shoelace/${component.path}';
            \`\`\`
            </sl-tab-panel>

            <sl-tab-panel name="react">\n
            To import this component as a [React component](/frameworks/react):
            \`\`\`js
            import { ${component.name} } from '@shoelace-style/shoelace/dist/react';
            \`\`\`
            </sl-tab-panel>
            </sl-tab-group>
          `;
        }

        if (props?.length) {
          result += `
            ## Properties
            ${createPropsTable(props)}
          `;
        }

        if (component.events?.length) {
          result += `
            ## Events
            ${createEventsTable(component.events)}
          `;
        }

        if (methods?.length) {
          result += `
            ## Methods

              Methods can be called by obtaining a reference to the element and calling
              el.methodName().

              Methods can be called by obtaining a ref to the element and calling
              ref.current.methodName().

            ${createMethodsTable(methods)}
          `;
        }

        if (component.slots?.length) {
          result += `
            ## Slots
            ${createSlotsTable(component.slots)}
          `;
        }

        if (component.cssProperties?.length) {
          result += `
            ## CSS Custom Properties
            ${createCustomPropertiesTable(component.cssProperties)}
          `;
        }

        if (component.cssParts?.length) {
          result += `
            ## CSS Parts
            ${createPartsTable(component.cssParts)}
          `;
        }

        if (component.animations?.length) {
          result += `
            ## Animations
            ${createAnimationsTable(component.animations)}

            Learn how to [customize animations](/getting-started/customizing#animations).
          `;
        }

        if (component.dependencies?.length) {
          result += `
            ## Dependencies

            This component imports the following dependencies.

            ${createDependenciesList(component.tagName, getAllComponents(metadata))}
          `;
        }

        // Strip whitespace so markdown doesn't process things as code blocks
        return result.replace(/^ +| +$/gm, '');
      });

      next(content);
    });

    // Wrap tables so we can scroll them horizontally when needed
    hook.doneEach(function () {
      const content = document.querySelector('.content');
      const tables = [...content.querySelectorAll('table')];

      tables.map(table => {
        table.outerHTML = `

            ${table.outerHTML}

        `;
      });
    });
  });
})();
<|endoftext|>


<commit_before>import {Link, useNavigate} from "react-router-dom";
import {useEffect, useState} from "react";

import {deleteTeam, getMyTeams} from "../api";
import I18n from "i18n-js";
import {ROLES} from "../utils/roles";
import {Page} from "../components/Page";
import {DropDownMenu} from "../components/DropDownMenu";
import {ReactComponent as SearchIcon} from "../icons/search.svg";
import binIcon from "../icons/bin-1.svg";
import blockedIcon from "../icons/allowances-no-talking.svg";

import "./MyTeams.scss"
import {Button} from "../components/Button";

export const MyTeams = () => {
    const navigate = useNavigate();
    const [teams, setTeams] = useState({
        teamSummaries: []
    });
    const [searchQuery, setSearchQuery] = useState("");
    const [displayedTeams, setDisplayedTeams] = useState([]);
    const [teamsFilter, setTeamsFilter] = useState({value: "ALL", label: ""});

    useEffect(() => {
        getMyTeams().then(teams => {
            setTeams(teams);
            setTeamsFilter({value: "ALL", label: `${I18n.t(`myteams.filters.all`)} (${teams.teamSummaries.length})`});
        })
    }, []);

    useEffect(() => {
        updateDisplayedTeams()
    }, [teams, searchQuery, teamsFilter])

    const updateDisplayedTeams = () => {
        const toDisplay = teams.teamSummaries.filter(team => {
            if (teamsFilter.value != team.role && teamsFilter.value != 'ALL') {
                return
            }

            if (searchQuery === "") {
                return team;
            } else if (team.name.toLowerCase().includes(searchQuery.toLowerCase())) {
                return team
            }
        })
        setDisplayedTeams(toDisplay)
    }

    const renderPrivateTag = viewable => {
        const tag =
            {I18n.t("myteams.private")}

        return (
            <>{viewable ? I18n.t("myteams.empty") : tag}</>
        )
    }

    const processDelete = team => {
        //TODO first show confirmation modal
        deleteTeam(team.id).then(() => {
            getMyTeams().then(teams => {
                setTeams(teams);
            })
        })
    }

    const renderAddMemberLink = team => {
        const link = <Link to={{pathname: "/", state: {team: team}}}>{I18n.t("myteams.add_members")}</Link>
        return (
            <>{ROLES.MEMBER !== team.role ? link : I18n.t("myteams.empty")}</>
        )
    }

    const renderDeleteButton = team => {
        const icon =  processDelete(team)}/>
        return (
            <>{[ROLES.OWNER, ROLES.ADMIN].includes(team.role) ? icon : I18n.t("myteams.empty")}</>
        )
    }

    const renderTeamsRow = team => {
        return (

            <Link to={`/team-details/${team.id}`}>{team.name}</Link>
            {team.membershipCount}
            {renderPrivateTag(team.viewable)}
            {renderAddMemberLink(team)}
            {renderDeleteButton(team)}

)
    }

    const renderTeamsSearch = () => {
        return (

                <input placeholder="Search" onChange={e => setSearchQuery(e.target.value)}/>
                <SearchIcon/>

        )
    }

    const renderFilterDropdown = () => {
        class FilterCount {
            constructor(value) {
                this.action = () => {
                    setTeamsFilter({value: this.value, label: this.name})
                }
                this.value = value
                if (value === 'ALL') {
                    this.count = teams.teamSummaries.length;
                    return this;
                }
                this.count = 0
            }

            get name() {
                return `${I18n.t(`myteams.filters.${this.value.toLowerCase()}`)} (${this.count})`
            }
        }

        const filters = ['ALL', ROLES.OWNER, ROLES.ADMIN, ROLES.MANAGER, ROLES.MEMBER]
        const options = filters.map(filter => new FilterCount(filter))

        teams.teamSummaries.forEach(team => {
            options.forEach(option => {
                if (option.value === team.role) {
                    option.count++;
                }
            })
        })

        return (

                <DropDownMenu title={teamsFilter.label} actions={options}/>

        )
    }

    const renderNewTeamButton = () => {
        const buttonClicked = () => {
            navigate("/");
        }
        return <Button onClick={buttonClicked} txt={I18n.t(`myteams.new_team`)} className="new-team-button"/>
    }

    const renderTeamsTable = () => {
        const headers = ["title", "members", "private", "member", "bin"];
        return (
            <Page>

My teams

                 {renderFilterDropdown()}{renderTeamsSearch()}{renderNewTeamButton()}

                        {headers.map(header =>
                            {I18n.t(`myteams.columns.${header}`)}
                        	)}

                    {displayedTeams.map(team => renderTeamsRow(team))}

            </Page>
        )
    }

    return (

TODO - delete confirmation modal

            {renderTeamsTable()}

    );

}<commit_msg>Make new team button point to correct page<commit_after>import {Link, useNavigate} from "react-router-dom";
import {useEffect, useState} from "react";

import {deleteTeam, getMyTeams} from "../api";
import I18n from "i18n-js";
import {ROLES} from "../utils/roles";
import {Page} from "../components/Page";
import {DropDownMenu} from "../components/DropDownMenu";
import {ReactComponent as SearchIcon} from "../icons/search.svg";
import binIcon from "../icons/bin-1.svg";
import blockedIcon from "../icons/allowances-no-talking.svg";

import "./MyTeams.scss"
import {Button} from "../components/Button";

export const MyTeams = () => {
    const navigate = useNavigate();
    const [teams, setTeams] = useState({
        teamSummaries: []
    });
    const [searchQuery, setSearchQuery] = useState("");
    const [displayedTeams, setDisplayedTeams] = useState([]);
    const [teamsFilter, setTeamsFilter] = useState({value: "ALL", label: ""});

    useEffect(() => {
        getMyTeams().then(teams => {
            setTeams(teams);
            setTeamsFilter({value: "ALL", label: `${I18n.t(`myteams.filters.all`)} (${teams.teamSummaries.length})`});
        })
    }, []);

    useEffect(() => {
        updateDisplayedTeams()
    }, [teams, searchQuery, teamsFilter])

    const updateDisplayedTeams = () => {
        const toDisplay = teams.teamSummaries.filter(team => {
            if (teamsFilter.value != team.role && teamsFilter.value != 'ALL') {
                return
            }

            if (searchQuery === "") {
                return team;
            } else if (team.name.toLowerCase().includes(searchQuery.toLowerCase())) {
                return team
            }
        })
        setDisplayedTeams(toDisplay)
    }

    const renderPrivateTag = viewable => {
        const tag =
            {I18n.t("myteams.private")}

        return (
            <>{viewable ? I18n.t("myteams.empty") : tag}</>
        )
    }

    const processDelete = team => {
        //TODO first show confirmation modal
        deleteTeam(team.id).then(() => {
            getMyTeams().then(teams => {
                setTeams(teams);
            })
        })
    }

    const renderAddMemberLink = team => {
        const link = <Link to={{pathname: "/", state: {team: team}}}>{I18n.t("myteams.add_members")}</Link>
        return (
            <>{ROLES.MEMBER !== team.role ? link : I18n.t("myteams.empty")}</>
        )
    }

    const renderDeleteButton = team => {
        const icon =  processDelete(team)}/>
        return (
            <>{[ROLES.OWNER, ROLES.ADMIN].includes(team.role) ? icon : I18n.t("myteams.empty")}</>
        )
    }

    const renderTeamsRow = team => {
        return (

            <Link to={`/team-details/${team.id}`}>{team.name}</Link>
            {team.membershipCount}
            {renderPrivateTag(team.viewable)}
            {renderAddMemberLink(team)}
            {renderDeleteButton(team)}

)
    }

    const renderTeamsSearch = () => {
        return (

                <input placeholder="Search" onChange={e => setSearchQuery(e.target.value)}/>
                <SearchIcon/>

        )
    }

    const renderFilterDropdown = () => {
        class FilterCount {
            constructor(value) {
                this.action = () => {
                    setTeamsFilter({value: this.value, label: this.name})
                }
                this.value = value
                if (value === 'ALL') {
                    this.count = teams.teamSummaries.length;
                    return this;
                }
                this.count = 0
            }

            get name() {
                return `${I18n.t(`myteams.filters.${this.value.toLowerCase()}`)} (${this.count})`
            }
        }

        const filters = ['ALL', ROLES.OWNER, ROLES.ADMIN, ROLES.MANAGER, ROLES.MEMBER]
        const options = filters.map(filter => new FilterCount(filter))

        teams.teamSummaries.forEach(team => {
            options.forEach(option => {
                if (option.value === team.role) {
                    option.count++;
                }
            })
        })

        return (

                <DropDownMenu title={teamsFilter.label} actions={options}/>

        )
    }

    const renderNewTeamButton = () => {
        const buttonClicked = () => {
            navigate("/new-team");
        }
        return <Button onClick={buttonClicked} txt={I18n.t(`myteams.new_team`)} className="new-team-button"/>
    }

    const renderTeamsTable = () => {
        const headers = ["title", "members", "private", "member", "bin"];
        return (
            <Page>

My teams

                 {renderFilterDropdown()}{renderTeamsSearch()}{renderNewTeamButton()}

                        {headers.map(header =>
                            {I18n.t(`myteams.columns.${header}`)}
                        	)}

                    {displayedTeams.map(team => renderTeamsRow(team))}

            </Page>
        )
    }

    return (

TODO - delete confirmation modal

            {renderTeamsTable()}

    );

}<|endoftext|>


<commit_before>/**
 * Backend for the Datalog web interface.
 */
var express = require('express'),
    util  = require('util'),
    spawn = require('child_process').spawn,
    fs = require('fs'),
    expressValidator = require('express-validator');

var app = express();

// serve static content from the 'static' directory
app.use(express.static('static'));

// serve static content from the 'examples' directory
app.use("/examples", express.static('examples'));

// use body parser to get access to form data
app.use(express.bodyParser());

// use the input validator
app.use(expressValidator);

// add a 'endsWith' function to String
String.prototype.endsWith = function(suffix) {
    return this.indexOf(suffix, this.length - suffix.length) !== -1;
};

// read configuration file
var config = JSON.parse(fs.readFileSync('config.json','utf8'));

// used to create temporary files
var counter = 0;

// Datalog REST service
app.post('/datalog', function (req, res) {

	// validate user input
  req.assert('ruleset', 'required').notEmpty();
  req.assert('ruleset', 'max. 4096 characters allowed').len(0, 4096);
  req.assert('ruleset', 'ruleset contains unallowed characters').is(/^[\[\]_=':\-\+<>\ \\a-zA-Z0-9\%\n\r(),;\.\t]+$/);

  req.assert('query', 'required').notEmpty();
  req.assert('query', 'max. 1024 characters allowed').len(0, 1024);
  req.assert('query', 'query contains unallowed characters').is(/^[_[\[\]=':\-\+<>\ \\a-zA-Z0-9\%\n\r(),;\.\t]+$/);

  var validationErrors = req.validationErrors();
  if (validationErrors) {
    res.json({
      'answer': answer,
      'error': 'There have been validation errors: ' + util.inspect(validationErrors) });
    return;
  }

  // write the ruleset to a temporary file
  counter++;
  var tempFile = config.tempDirectory + '/ruleset-' + counter + '.dl';
  fs.writeFile(tempFile, req.body.ruleset, function(err) {
    if(err) {
      console.log(err);
    }
  });

  // start a DES process and connect the streams
  var desProcess = spawn(config.desExecutable);
  var desProcessIsRunning = true;
  var computationTimeExceeded = false;
  var answer = '';

  // terminates the process if the computation takes too much time
  setTimeout(function() {
  	if (desProcessIsRunning) {
	  	computationTimeExceeded = true;
	  	console.log("Terminating DES due to timeout.");
	  	desProcess.kill('SIGKILL');
	  	try {
	  	  fs.unlinkSync(tempFile);
	    } catch (err) {}
  	}
  }, config.desTimeLimitMillis);

  // reading the standard output of DES
  desProcess.stdout.on('data', function (data) {
    data = '' + data;
    if (!data.match(/^\*/g)) {
      data = data.replace(/DES>/g, '');
      data = data.replace(/\r\n\r\n/g, '\n');
      answer = answer + data;
    }
  });

  // send the answer after the computation has been finished
  desProcess.on('exit', function (code) {
    desProcessIsRunning = false;
    try {
    	fs.unlinkSync(tempFile);
    } catch (err) {}
    if (computationTimeExceeded) {
    	answer = "---  Sorry, computation time exceeded...  ----"
    }
    res.json({
      'answer': answer
    });
  });

  // consult the previously written file
  desProcess.stdin.write('/consult ' + tempFile + '\n');

	// transform query into a single line string
  var queryLines = req.body.query.split(/\n/);
  var query = "";
  queryLines.forEach(function(line) {
  	query += line + " ";
  });
	console.log("Executing query " + counter + ": " + query);

  // submit query
  desProcess.stdin.write(query + '\n');

  // terminate the process
  desProcess.stdin.end();
});

// Examples REST service. Delivers the examples to the client.
app.get('/examples', function (req, res) {

	// reads the contents of the examples directory
	// and sends a list to the client.

	// the examples are delivered as static content
  var exampleDescriptors = [];
  var exampleFiles = fs.readdirSync(config.examplesDirectory);
  exampleFiles.forEach(function(file) {
    if (file.endsWith(".json")) {
	  	var fileContents = fs.readFileSync(config.examplesDirectory + '/' + file,'utf8');
			var example = JSON.parse(fileContents);
			exampleDescriptors.push({
				"name": example.name,
				"description": example.description,
				"source": example.source,
				"url": "/examples" + "/" + file,
			});
		}
  });
	res.json(exampleDescriptors);
});

app.listen(config.port);
console.log('Started web service on port ' + config.port + '.');
<commit_msg>Removed superfluous info messages from the Datalog answer text.<commit_after>/**
 * Backend for the Datalog web interface.
 */
var express = require('express'),
    util  = require('util'),
    spawn = require('child_process').spawn,
    fs = require('fs'),
    expressValidator = require('express-validator');

var app = express();

// serve static content from the 'static' directory
app.use(express.static('static'));

// serve static content from the 'examples' directory
app.use("/examples", express.static('examples'));

// use body parser to get access to form data
app.use(express.bodyParser());

// use the input validator
app.use(expressValidator);

// add a 'endsWith' function to String
String.prototype.endsWith = function(suffix) {
    return this.indexOf(suffix, this.length - suffix.length) !== -1;
};

// read configuration file
var config = JSON.parse(fs.readFileSync('config.json','utf8'));

// used to create temporary files
var counter = 0;

// Datalog REST service
app.post('/datalog', function (req, res) {

  // validate user input
  // WARNING: Don't allow forward slashes!
  req.assert('ruleset', 'required').notEmpty();
  req.assert('ruleset', 'max. 4096 characters allowed').len(0, 4096);
  req.assert('ruleset', 'ruleset contains unallowed characters').is(/^[\[\]_=':\-\+<>\ \\a-zA-Z0-9\%\n\r(),;\.\t]+$/);

  req.assert('query', 'required').notEmpty();
  req.assert('query', 'max. 1024 characters allowed').len(0, 1024);
  req.assert('query', 'query contains unallowed characters').is(/^[_[\[\]=':\-\+<>\ \\a-zA-Z0-9\%\n\r(),;\.\t]+$/);

  var validationErrors = req.validationErrors();
  if (validationErrors) {
    res.json({
      'answer': answer,
      'error': 'There have been validation errors: ' + util.inspect(validationErrors) });
    return;
  }

  // write the ruleset to a temporary file
  counter++;
  var tempFile = config.tempDirectory + '/ruleset-' + counter + '.dl';
  fs.writeFile(tempFile, req.body.ruleset, function(err) {
    if(err) {
      console.log(err);
    }
  });

  // start a DES process and connect the streams
  var desProcess = spawn(config.desExecutable);
  var desProcessIsRunning = true;
  var computationTimeExceeded = false;
  var answer = '';

  // terminates the process if the computation takes too much time
  setTimeout(function() {
  	if (desProcessIsRunning) {
	  	computationTimeExceeded = true;
	  	console.log("Terminating DES due to timeout.");
	  	desProcess.kill('SIGKILL');
	  	try {
	  	  fs.unlinkSync(tempFile);
	    } catch (err) {}
  	}
  }, config.desTimeLimitMillis);

  // reading the standard output of DES
  desProcess.stdout.on('data', function (data) {
    data = '' + data;
    if (!data.match(/^\*/g)) {
      data = data.replace(/DES>/g, '');
      data = data.replace(/\r\n\r\n/g, '\n');
      data = data.replace(/Info: [0-9]+ rule[s]? consulted\./, '');
      data = data.replace(/Info: [0-9]+ tuple[s]? computed\./, '');
      answer = answer + data;
    }
  });

  // send the answer after the computation has been finished
  desProcess.on('exit', function (code) {
    desProcessIsRunning = false;
    try {
    	fs.unlinkSync(tempFile);
    } catch (err) {}
    if (computationTimeExceeded) {
    	answer = "---  Sorry, computation time exceeded...  ----"
    } else {
    	var answerLines = answer.split('\n');
    	answer = '';
    	answerLines.forEach(function(line) {
    		if (line.trim() != '') {
  				answer += line + "\n";
  			}
  		});
    }
    res.json({
      'answer': answer
    });
  });

  // consult the previously written file
  desProcess.stdin.write('/consult ' + tempFile + '\n');

	// transform query into a single line string
  var queryLines = req.body.query.split(/\n/);
  var query = "";
  queryLines.forEach(function(line) {
  	query += line + " ";
  });
	console.log("Executing query " + counter + ": " + query);

  // submit query
  desProcess.stdin.write(query + '\n');

  // terminate the process
  desProcess.stdin.end();
});

// Examples REST service. Delivers the examples to the client.
app.get('/examples', function (req, res) {

  // reads the contents of the examples directory
  // and sends a list to the client.

  // the examples are delivered as static content
  var exampleDescriptors = [];
  var exampleFiles = fs.readdirSync(config.examplesDirectory);
  exampleFiles.forEach(function(file) {
    if (file.endsWith(".json")) {
	  	var fileContents = fs.readFileSync(config.examplesDirectory + '/' + file,'utf8');
			var example = JSON.parse(fileContents);
			exampleDescriptors.push({
				"name": example.name,
				"description": example.description,
				"source": example.source,
				"url": "/examples" + "/" + file,
			});
		}
  });
	res.json(exampleDescriptors);
});

app.listen(config.port);
console.log('Started web service on port ' + config.port + '.');
<|endoftext|>


<commit_before>const path = require('path');
const webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');

new WebpackDevServer(webpack({
  devtool: 'eval',
  entry: [
    'webpack-dev-server/client?http://localhost:3000',
    'webpack/hot/only-dev-server',
    'react-hot-loader/patch',
    './index'
  ],
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin()
  ],
  resolve: {
    extensions: ['.js', '.jsx']
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        loader: 'babel-loader',
        include: [
          path.join(__dirname, '../site'),
          path.join(__dirname, '../src'),
          path.join(__dirname, '../libs')
        ]
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      {
        test: /\.scss$/,
        use: ['style-loader', 'css-loader', 'sass-loader']
      },
      {
        test: /\.(eot|svg|ttf|woff|woff2)(\?.+)?$/,
        loader : 'file-loader'
      },
      {
        test: /\.(jpe?g|png|gif)(\?.+)?$/,
        loader : 'url-loader'
      },
      {
        test: /\.md$/,
        loader : 'raw-loader'
      }
    ]
  }
}), {
  publicPath: '/',
  hot: true,
  historyApiFallback: true
}).listen(3000, 'localhost', error => {
  if (error) {
    throw error;
  }
});
<commit_msg>Add some colors to the webpack's output<commit_after>const path = require('path');
const webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');

new WebpackDevServer(webpack({
  devtool: 'eval',
  entry: [
    'webpack-dev-server/client?http://localhost:3000',
    'webpack/hot/only-dev-server',
    'react-hot-loader/patch',
    './index'
  ],
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin()
  ],
  resolve: {
    extensions: ['.js', '.jsx']
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        loader: 'babel-loader',
        include: [
          path.join(__dirname, '../site'),
          path.join(__dirname, '../src'),
          path.join(__dirname, '../libs')
        ]
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      {
        test: /\.scss$/,
        use: ['style-loader', 'css-loader', 'sass-loader']
      },
      {
        test: /\.(eot|svg|ttf|woff|woff2)(\?.+)?$/,
        loader : 'file-loader'
      },
      {
        test: /\.(jpe?g|png|gif)(\?.+)?$/,
        loader : 'url-loader'
      },
      {
        test: /\.md$/,
        loader : 'raw-loader'
      }
    ]
  }
}), {
  publicPath: '/',
  hot: true,
  historyApiFallback: true,
  stats: { colors: true }
}).listen(3000, 'localhost', error => {
  if (error) {
    throw error;
  }
});
<|endoftext|>


<commit_before>/**
 * The uploading progress feature
 *
 * Copyright (C) 2010-2011 Nikolay Nemshilov
 */
var Uploader = new Widget({
  extend: {
    version: '2.2.0',

    EVENTS: $w('start update finish error'),

    Options: {
      url:         '/progress',
      param:       'X-Progress-ID',

      timeout:     1000,
      round:       0,
      fxDuration:  400,

      cssRule:     '[data-uploader]'
    }
  },

  /**
   * Basic constructor
   *
   * @param mixed a form reference
   * @param Object options
   */
  initialize: function(form, options) {
    this.form = form = $(form);

    // trying to find an existing progress-bar
    var element = form.first('.rui-uploader');

    this
      .$super('uploader', element)
      .setOptions(options, this.form)
      .addClass('rui-progress-bar')
      .insert([
        this.bar = this.first('.bar') || $E('div', {'class': 'bar'}),
        this.num = this.first('.num') || $E('div', {'class': 'num'})
      ]);

    if (!element) {
      this.insertTo(form);
    }
  },

  /**
   * Starts the uploading monitoring
   *
   * @return Uploader this
   */
  start: function() {
    var data = {state: 'starting'};
    return this.paint(data).prepare().request().fire('start', {data: data});
  },

// protected

  // updates uploading bar progress
  update: function(data) {
    this.paint(data).fire('update', {data: data});

    switch (data.state) {
      case 'starting':
      case 'uploading':
        R(this.request).bind(this).delay(this.options.timeout);
        break;
      case 'done':
        this.fire('finish', {data: data});
        break;
      case 'error':
        this.fire('error', {data: data});
        break;
    }

    return this;
  },

  // changes the actual element styles
  paint: function(data) {
    var percent = (this.percent || 0)/100;

    switch (data.state) {
      case 'starting':  percent = 0; break;
      case 'done':      percent = 1; break;
      case 'uploading': percent = data.received / (data.size||1); break;
    }

    this.percent = R(percent * 100).round(this.options.round);

    if (this.percent === 0 || !RightJS.Fx || !this.options.fxDuration) {
      this.bar._.style.width = this.percent + '%';
      this.num._.innerHTML   = this.percent + '%';
    } else {
      this.bar.morph({width: this.percent + '%'}, {duration: this.options.fxDuration});
      R(function() {
        this.num._.innerHTML = this.percent + '%';
      }).bind(this).delay(this.options.fxDuration / 2);
    }

    // marking the failed uploads
    this[data.state === 'error' ? 'addClass' : 'removeClass']('rui-progress-bar-failed');

    return this;
  },

  // sends a request to the server
  request: function() {
    Xhr.load(this.options.url + "?" + this.options.param + "=" + this.uid, {
      evalJSON: false,
      onSuccess: R(function(xhr) {
        this.update(new Function('return '+xhr.text)());
      }).bind(this)
    });

    return this;
  },

  // prepares the form to carry the x-progress-id param
  prepare: function() {
    this.uid = "";
    for (i = 0; i < 32; i++) { this.uid += Math.random(0, 15).toString(16); }

    var param = this.options.param;
    var url = this.form.get('action').replace(new RegExp('(\\?|&)'+RegExp.escape(param) + '=[^&]*', 'i'), '');
    this.form.set('action', url + (R(url).includes('?') ? '&' : '?') + param + '=' + this.uid);

    this.show();

    return this;
  }

});
<commit_msg>Uplaoder fix for incorrect content-type apache sends in some cases<commit_after>/**
 * The uploading progress feature
 *
 * Copyright (C) 2010-2011 Nikolay Nemshilov
 */
var Uploader = new Widget({
  extend: {
    version: '2.2.1',

    EVENTS: $w('start update finish error'),

    Options: {
      url:         '/progress',
      param:       'X-Progress-ID',

      timeout:     1000,
      round:       0,
      fxDuration:  400,

      cssRule:     '[data-uploader]'
    }
  },

  /**
   * Basic constructor
   *
   * @param mixed a form reference
   * @param Object options
   */
  initialize: function(form, options) {
    this.form = form = $(form);

    // trying to find an existing progress-bar
    var element = form.first('.rui-uploader');

    this
      .$super('uploader', element)
      .setOptions(options, this.form)
      .addClass('rui-progress-bar')
      .insert([
        this.bar = this.first('.bar') || $E('div', {'class': 'bar'}),
        this.num = this.first('.num') || $E('div', {'class': 'num'})
      ]);

    if (!element) {
      this.insertTo(form);
    }
  },

  /**
   * Starts the uploading monitoring
   *
   * @return Uploader this
   */
  start: function() {
    var data = {state: 'starting'};
    return this.paint(data).prepare().request().fire('start', {data: data});
  },

// protected

  // updates uploading bar progress
  update: function(data) {
    this.paint(data).fire('update', {data: data});

    switch (data.state) {
      case 'starting':
      case 'uploading':
        R(this.request).bind(this).delay(this.options.timeout);
        break;
      case 'done':
        this.fire('finish', {data: data});
        break;
      case 'error':
        this.fire('error', {data: data});
        break;
    }

    return this;
  },

  // changes the actual element styles
  paint: function(data) {
    var percent = (this.percent || 0)/100;

    switch (data.state) {
      case 'starting':  percent = 0; break;
      case 'done':      percent = 1; break;
      case 'uploading': percent = data.received / (data.size||1); break;
    }

    this.percent = R(percent * 100).round(this.options.round);

    if (this.percent === 0 || !RightJS.Fx || !this.options.fxDuration) {
      this.bar._.style.width = this.percent + '%';
      this.num._.innerHTML   = this.percent + '%';
    } else {
      this.bar.morph({width: this.percent + '%'}, {duration: this.options.fxDuration});
      R(function() {
        this.num._.innerHTML = this.percent + '%';
      }).bind(this).delay(this.options.fxDuration / 2);
    }

    // marking the failed uploads
    this[data.state === 'error' ? 'addClass' : 'removeClass']('rui-progress-bar-failed');

    return this;
  },

  // sends a request to the server
  request: function() {
    Xhr.load(this.options.url + "?" + this.options.param + "=" + this.uid, {
      evalJS:   false,
      evalJSON: false,
      onSuccess: R(function(xhr) {
        this.update(new Function('return '+xhr.text)());
      }).bind(this)
    });

    return this;
  },

  // prepares the form to carry the x-progress-id param
  prepare: function() {
    this.uid = "";
    for (i = 0; i < 32; i++) { this.uid += Math.random(0, 15).toString(16); }

    var param = this.options.param;
    var url = this.form.get('action').replace(new RegExp('(\\?|&)'+RegExp.escape(param) + '=[^&]*', 'i'), '');
    this.form.set('action', url + (R(url).includes('?') ? '&' : '?') + param + '=' + this.uid);

    this.show();

    return this;
  }

});
<|endoftext|>


<commit_before>function validateEnquiryForm(){
	var valid = true;
	var e = EnquiryFormValidator;
	for (var el in e) {
		var elItem = document.getElementById('Form_EnquiryForm_'+el);
		elItem.className = elItem.className.replace(/\binvalid\b/,'');
		if (e[el] == 'Email') { // Email
			var elValue = elItem.value.replace(/^\s+|\s+$/g, ''); // trim
			validRegExp = /^[_a-z0-9-+]+(\.[_a-z0-9-+]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$/i;
			if (elValue == '' || elValue.search(validRegExp) == -1) {
				elValue = false;
			}
		}
		else if (e[el] == 'Text') { // Input / TextArea
			var elValue = elItem.value.replace(/^\s+|\s+$/g, ''); // trim
			if (elValue == '') {
				elValue = false;
			}
		}
		else if (e[el] == 'Select') { // Select
			var elValue = elItem.options[elItem.selectedIndex].value;
			if (elValue == '') {
				elValue = false;
			}
		}
		else if (e[el] == 'Radio') { // Radio
			var elValue = false;
			var rdios = document.getElementsByName(el);
			for(var i = 0; i < rdios.length; i++) {
				if(rdios[i].checked == true) {
					elValue = true;
				}
			}
		}
		if (elValue === false) {
			valid = false;
			elItem.className = elItem.className + " invalid";
		}
	}
	if (valid === false) {
		alert('Please make sure all the required fields are filled in correctly.');
		return false;
	}
	document.getElementById('Form_EnquiryForm_action_SendEnquiryForm').disabled = true;
	return true;
}

function initEnquiryFormValidator(){
	if(EnquiryFormValidator && document.getElementById('Form_EnquiryForm')) {
		document.getElementById('Form_EnquiryForm').onsubmit=validateEnquiryForm;
	}
}

function addEnquiryFormLoadEvent(func){
	var oldonload = window.onload;
	if (typeof window.onload != 'function') window.onload = func;
	else {
		window.onload = function(){
		oldonload();
		func();
		}
	}

}

addEnquiryFormLoadEvent(initEnquiryFormValidator);<commit_msg>Spacing<commit_after>function validateEnquiryForm() {
	var valid = true;
	var e = EnquiryFormValidator;
	for (var el in e) {
		var elItem = document.getElementById('Form_EnquiryForm_'+el);
		elItem.className = elItem.className.replace(/\binvalid\b/,'');
		if (e[el] == 'Email') { // Email
			var elValue = elItem.value.replace(/^\s+|\s+$/g, ''); // trim
			validRegExp = /^[_a-z0-9-+]+(\.[_a-z0-9-+]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$/i;
			if (elValue == '' || elValue.search(validRegExp) == -1) {
				elValue = false;
			}
		}
		else if (e[el] == 'Text') { // Input / TextArea
			var elValue = elItem.value.replace(/^\s+|\s+$/g, ''); // trim
			if (elValue == '') {
				elValue = false;
			}
		}
		else if (e[el] == 'Select') { // Select
			var elValue = elItem.options[elItem.selectedIndex].value;
			if (elValue == '') {
				elValue = false;
			}
		}
		else if (e[el] == 'Radio') { // Radio
			var elValue = false;
			var rdios = document.getElementsByName(el);
			for(var i = 0; i < rdios.length; i++) {
				if(rdios[i].checked == true) {
					elValue = true;
				}
			}
		}
		if (elValue === false) {
			valid = false;
			elItem.className = elItem.className + " invalid";
		}
	}
	if (valid === false) {
		alert('Please make sure all the required fields are filled in correctly.');
		return false;
	}
	document.getElementById('Form_EnquiryForm_action_SendEnquiryForm').disabled = true;
	return true;
}

function initEnquiryFormValidator() {
	if(EnquiryFormValidator && document.getElementById('Form_EnquiryForm')) {
		document.getElementById('Form_EnquiryForm').onsubmit=validateEnquiryForm;
	}
}

function addEnquiryFormLoadEvent(func) {
	var oldonload = window.onload;
	if (typeof window.onload != 'function') window.onload = func;
	else {
		window.onload = function(){
			oldonload();
			func();
		}
	}

}

addEnquiryFormLoadEvent(initEnquiryFormValidator);<|endoftext|>


<commit_before>videojs.addLanguage("es",{
 "Play": "Reproducción",
 "Pause": "Pausa",
 "Current Time": "Tiempo reproducido",
 "Duration Time": "Duración total",
 "Remaining Time": "Tiempo restante",
 "Stream Type": "Tipo de secuencia",
 "LIVE": "DIRECTO",
 "Loaded": "Cargado",
 "Progress": "Progreso",
 "Fullscreen": "Pantalla completa",
 "Non-Fullscreen": "Pantalla no completa",
 "Mute": "Silenciar",
 "Unmuted": "No silenciado",
 "Playback Rate": "Velocidad de reproducción",
 "Subtitles": "Subtítulos",
 "subtitles off": "Subtítulos desactivados",
 "Captions": "Subtítulos especiales",
 "captions off": "Subtítulos especiales desactivados",
 "Chapters": "Capítulos",
 "You aborted the video playback": "Ha interrumpido la reproducción del vídeo.",
 "A network error caused the video download to fail part-way.": "Un error de red ha interrumpido la descarga del vídeo.",
 "The video could not be loaded, either because the server or network failed or because the format is not supported.": "No se ha podido cargar el vídeo debido a un fallo de red o del servidor o porque el formato es incompatible.",
 "The video playback was aborted due to a corruption problem or because the video used features your browser did not support.": "La reproducción de vídeo se ha interrumpido por un problema de corrupción de datos o porque el vídeo precisa funciones que su navegador no ofrece.",
 "No compatible source was found for this video.": "No se ha encontrado ninguna fuente compatible con este vídeo."
});<commit_msg>Delete es.js<commit_after><|endoftext|>


<commit_before>var controllers = angular.module('controllers');

controllers.controller('MapCtrl', ['$scope', '$rootScope', 'Search', function ($scope, $rootScope, Search) {
    // Mapbox doesn't need its own var - it automatically attaches to Leaflet's L.
    require('mapbox.js');
    // Use Awesome Markers lib to produce font-icon map markers
    require('../../../src/leaflet.awesome-markers.js');
    // Marker clustering
    require('../../../node_modules/leaflet.markercluster/dist/leaflet.markercluster.js');

    // Initialize the map, using Affinity Bridge's mapbox account.
    var map = L.mapbox.map('map', 'affinitybridge.ia7h38nj');

    // TODO: re-enable when UserLocation service is added
    // Object that holds user location - adds a layer with user's location marker
    //    var myLocation = new UserLocation(map);
    //
    //    map.on('load', function () {
    //        // Try to add user location marker
    //        getUserLocation();
    //    });

    // Initialize the empty layer for the markers, and add it to the map.
    // TODO: don't use global var here
    clusterLayer = new L.MarkerClusterGroup({
        zoomToBoundsOnClick: false,
        spiderfyDistanceMultiplier: 2,
        showCoverageOnHover: false
    }).addTo(map);
    // When user clicks on a cluster, zoom directly to its bounds.  If we don't do this,
    // they have to click repeatedly to zoom in enough for the cluster to spiderfy.
    clusterLayer.on('clusterclick', function (a) {
        // Close any popups that are open already. This helps if we came via "show on map" link,
        // which spawns an unbound popup.
        map.closePopup();
        // If the markers in this cluster are all in the same place, spiderfy on click.
        var bounds = a.layer.getBounds();
        if (bounds._northEast.equals(bounds._southWest)) {
            a.layer.spiderfy();
        } else {
            // If the markers in this cluster are NOT all in the same place, zoom in on them.
            a.layer.zoomToBounds();
        }
    });

    var polygonLayer = L.geoJson();
    map.addLayer(polygonLayer);

    // Match possible Activity Categories to Humanitarian Font icons.
    var iconGlyphs = {
        'CASH': {glyph: 'ocha-sector-cash', markerColor: '#a48658' },
        'EDUCATION': {glyph: 'ocha-sector-education', markerColor: '#c00000' },
        'FOOD': {glyph: 'ocha-sector-foodsecurity', markerColor: '#006600' },
        'HEALTH': {glyph: 'ocha-sector-health', markerColor: '#08a1d9' },
        'NFI': {glyph: 'ocha-item-reliefgood', markerColor: '#f96a1b' },
        'PROTECTION': {glyph: 'ocha-sector-protection', markerColor: '#1f497d' },
        'SHELTER': {glyph: 'ocha-sector-shelter', markerColor: '#989aac' },
        'WASH': {glyph: 'ocha-sector-wash', markerColor: '#7030a0' }
    };

    // TODO: remove global
    iconObjects = {};

    // Create the icon objects. We'll reuse the same icon for all markers in the same category.
    for (var category in iconGlyphs) {
        iconObjects[category] = L.AwesomeMarkers.icon({
            icon: iconGlyphs[category].glyph,
            prefix: 'icon', // necessary because Humanitarian Fonts prefixes its icon names with "icon"
            iconColor: iconGlyphs[category].markerColor,
            markerColor: "white",
            extraClasses: category
        });
    }

    var onChange = function(event) {
        var results = Search.currResults();

        // Clear all the map markers.
        clusterLayer.clearLayers();

        // Initialize the list-view output.
        //var listOutput = '
Services
';

        // Initialize a list where we'll store the current markers for easy reference when
        // building the "show on map" functionality.  TODO: can we streamline this out?
        var markers = {};

        // Loop through the filtered results, adding the markers back to the map.
        results.forEach( function (feature) {
            // Add the filtered markers back to the map's data layer
            clusterLayer.addLayer(feature.properties.marker);
            // Store the marker for easy reference.
            markers[feature.id] = feature.properties.marker;
            // Build the output for the filtered list view
            //listOutput += renderServiceText(feature, "list");
        } );

        // Replace the contents of the list div with this new, filtered output.
        //$('#list').html(listOutput);

        // According functionality for the list - expand item when its header is clicked
        //$(".serviceText > header").click(function(event) {
        //    event.preventDefault();
        //    $(this).parent().toggleClass('expand');
        //    // Toggle the text of the "Show details" / "Hide details" link
        //    if ($(this).find('.show-details').html() === "Show details") {
        //        $(this).find('.show-details').html("Hide details");
        //    } else {
        //        $(this).find('.show-details').html("Show details");
        //    }
        //});

        // Bind "show on map" behavior.  Do this here because now the list exists.
        //$(".show-on-map").click(function(e) {
        //    // Get the unique ID of this service.
        //    var id = e.target.id;
        //    // Close any popups that are open already.
        //    map.closePopup();
        //    // Fire the map/list toggler click event, to switch to viewing the map.
        //    $("#map-list-toggler").click();
        //    // Pan and zoom the map.
        //    map.panTo(markers[id]._latlng);
        //    if (map.getZoom() < 12) { map.setZoom(12); }
        //    // Clone the popup for this marker.  We'll show it at the correct lat-long, but
        //    // unbound from the marker.  We do this in case the marker is in a cluster.
        //    var unboundPopup = markers[id].getPopup();
        //    // Send the service's unique ID as the className of the popup, so that the "Show
        //    // details" binding will work as usual when the popupopen event fires; also, offset
        //    // the Y position so the popup is a little bit above the marker or cluster.
        //    map.openPopup(L.popup({className:id, offset: new L.Point(0,-25)})
        //        .setLatLng(markers[id]._latlng)
        //        .setContent(markers[id].getPopup()._content));
        //});
    };

    $rootScope.$on('FILTER_CHANGED', onChange);
}]);
<commit_msg>use leaflet to determine geolocation<commit_after>var controllers = angular.module('controllers');

controllers.controller('MapCtrl', ['$scope', '$rootScope', 'Search', function ($scope, $rootScope, Search) {
    // Mapbox doesn't need its own var - it automatically attaches to Leaflet's L.
    require('mapbox.js');
    // Use Awesome Markers lib to produce font-icon map markers
    require('../../../src/leaflet.awesome-markers.js');
    // Marker clustering
    require('../../../node_modules/leaflet.markercluster/dist/leaflet.markercluster.js');

    // Initialize the map, using Affinity Bridge's mapbox account.
    var map = L.mapbox.map('map', 'affinitybridge.ia7h38nj');

    map.locate({setView: false});
    map.on("locationfound", function(e) {
        L.marker(e.latlng).addTo(map);
    });

    // Initialize the empty layer for the markers, and add it to the map.
    // TODO: don't use global var here
    clusterLayer = new L.MarkerClusterGroup({
        zoomToBoundsOnClick: false,
        spiderfyDistanceMultiplier: 2,
        showCoverageOnHover: false
    }).addTo(map);
    // When user clicks on a cluster, zoom directly to its bounds.  If we don't do this,
    // they have to click repeatedly to zoom in enough for the cluster to spiderfy.
    clusterLayer.on('clusterclick', function (a) {
        // Close any popups that are open already. This helps if we came via "show on map" link,
        // which spawns an unbound popup.
        map.closePopup();
        // If the markers in this cluster are all in the same place, spiderfy on click.
        var bounds = a.layer.getBounds();
        if (bounds._northEast.equals(bounds._southWest)) {
            a.layer.spiderfy();
        } else {
            // If the markers in this cluster are NOT all in the same place, zoom in on them.
            a.layer.zoomToBounds();
        }
    });

    var polygonLayer = L.geoJson();
    map.addLayer(polygonLayer);

    // Match possible Activity Categories to Humanitarian Font icons.
    var iconGlyphs = {
        'CASH': {glyph: 'ocha-sector-cash', markerColor: '#a48658' },
        'EDUCATION': {glyph: 'ocha-sector-education', markerColor: '#c00000' },
        'FOOD': {glyph: 'ocha-sector-foodsecurity', markerColor: '#006600' },
        'HEALTH': {glyph: 'ocha-sector-health', markerColor: '#08a1d9' },
        'NFI': {glyph: 'ocha-item-reliefgood', markerColor: '#f96a1b' },
        'PROTECTION': {glyph: 'ocha-sector-protection', markerColor: '#1f497d' },
        'SHELTER': {glyph: 'ocha-sector-shelter', markerColor: '#989aac' },
        'WASH': {glyph: 'ocha-sector-wash', markerColor: '#7030a0' }
    };

    // TODO: remove global
    iconObjects = {};

    // Create the icon objects. We'll reuse the same icon for all markers in the same category.
    for (var category in iconGlyphs) {
        iconObjects[category] = L.AwesomeMarkers.icon({
            icon: iconGlyphs[category].glyph,
            prefix: 'icon', // necessary because Humanitarian Fonts prefixes its icon names with "icon"
            iconColor: iconGlyphs[category].markerColor,
            markerColor: "white",
            extraClasses: category
        });
    }

    var onChange = function(event) {
        var results = Search.currResults();

        // Clear all the map markers.
        clusterLayer.clearLayers();

        // Initialize the list-view output.
        //var listOutput = '
Services
';

        // Initialize a list where we'll store the current markers for easy reference when
        // building the "show on map" functionality.  TODO: can we streamline this out?
        var markers = {};

        // Loop through the filtered results, adding the markers back to the map.
        results.forEach( function (feature) {
            // Add the filtered markers back to the map's data layer
            clusterLayer.addLayer(feature.properties.marker);
            // Store the marker for easy reference.
            markers[feature.id] = feature.properties.marker;
            // Build the output for the filtered list view
            //listOutput += renderServiceText(feature, "list");
        } );

        // Replace the contents of the list div with this new, filtered output.
        //$('#list').html(listOutput);

        // According functionality for the list - expand item when its header is clicked
        //$(".serviceText > header").click(function(event) {
        //    event.preventDefault();
        //    $(this).parent().toggleClass('expand');
        //    // Toggle the text of the "Show details" / "Hide details" link
        //    if ($(this).find('.show-details').html() === "Show details") {
        //        $(this).find('.show-details').html("Hide details");
        //    } else {
        //        $(this).find('.show-details').html("Show details");
        //    }
        //});

        // Bind "show on map" behavior.  Do this here because now the list exists.
        //$(".show-on-map").click(function(e) {
        //    // Get the unique ID of this service.
        //    var id = e.target.id;
        //    // Close any popups that are open already.
        //    map.closePopup();
        //    // Fire the map/list toggler click event, to switch to viewing the map.
        //    $("#map-list-toggler").click();
        //    // Pan and zoom the map.
        //    map.panTo(markers[id]._latlng);
        //    if (map.getZoom() < 12) { map.setZoom(12); }
        //    // Clone the popup for this marker.  We'll show it at the correct lat-long, but
        //    // unbound from the marker.  We do this in case the marker is in a cluster.
        //    var unboundPopup = markers[id].getPopup();
        //    // Send the service's unique ID as the className of the popup, so that the "Show
        //    // details" binding will work as usual when the popupopen event fires; also, offset
        //    // the Y position so the popup is a little bit above the marker or cluster.
        //    map.openPopup(L.popup({className:id, offset: new L.Point(0,-25)})
        //        .setLatLng(markers[id]._latlng)
        //        .setContent(markers[id].getPopup()._content));
        //});
    };

    $rootScope.$on('FILTER_CHANGED', onChange);
}]);
<|endoftext|>


<commit_before>var path = require('path');
var assert = require('assert');
var sinon = require('sinon');
var gutil = require('gulp-util');
var proxyquire = require('proxyquire');
var fs = require('fs');
var del = sinon.stub().returns(Promise.resolve());
var write = proxyquire('../lib/write', { fs: fs, del: del });
var verbose = true;
var dirname = path.join(__dirname, '../');

describe('write()', function () {
  var fakeFileName;
  var fakeFilePath;

  beforeEach(function () {
    sinon.stub(fs, 'readFile');

    fakeFileName = 'app_d41d8cd98f.js';
    fakeFilePath = path.join('src', fakeFileName);
  });

  afterEach(function () {
    fs.readFile.restore();
    del.reset();
  });

  describe('with an invalid configuration', function () {
    it('should throw an error if output path is missing', function () {
      var stream = write(null, verbose);

      stream.on('error', function (err) {
        assert.equal(err.message, 'required argument "dest path" for revise.write() is missing');
      });

      stream.write(createFile(fakeFilePath));
    });
  });

  describe('with a valid configuration', function () {
    var stream;

    beforeEach(function () {
      stream = write('dist', verbose);
    });

    it('should push the original file and create the .rev', function () {
      var file = createFile(fakeFilePath);
      var filePath = file.path;
      var fileDir = path.dirname(filePath);
      var revFilePath = path.join(fileDir, 'app.js.rev');
      var pushedOriginalFile = false;

      stream.on('data', function (file) {
        if (pushedOriginalFile) {
          assert.equal(file.path, revFilePath);
          assert.equal(file.contents.toString(), fakeFileName);
          return;
        }

        pushedOriginalFile = true;
        assert.equal(file.path, filePath);
      });

      stream.write(file);
    });

    it('should ignore files that miss the beforeRev prop', function () {
      var spy = sinon.stub();

      stream.on('data', spy);
      stream.write(createFile('src/app.js', true));

      assert.equal(spy.callCount, 1);
    });

    it('should read the existing revision', function () {
      stream.write(createFile(fakeFilePath));

      assert.equal(fs.readFile.callCount, 1);
      assert.equal(fs.readFile.firstCall.args[0], path.join(dirname, 'dist', 'app.js.rev'));
    });

    it('should delete the old revision', function () {
      stream.write(createFile(fakeFilePath));
      fs.readFile.callArgWith(2, null, 'app_abcdef.js');

      assert.equal(del.callCount, 1);
      assert.deepEqual(del.firstCall.args, [
        [
          path.join(dirname, 'dist', 'app_abcdef.js'),
          path.join(dirname, 'dist', 'app_abcdef.js.map')
        ]
      ]);
    });

    it('should not delete the old revision if it\'s the same as the new one', function () {
      stream.write(createFile(fakeFilePath));
      fs.readFile.callArgWith(2, null, fakeFileName);

      assert.equal(del.callCount, 0);
    });
  });
});

function createFile (pth, omitBeforeRev) {
  var file = new gutil.File({
    path: path.join(dirname, pth),
    contents: new Buffer('')
  });

  if (!omitBeforeRev) {
    var beforeRev = pth.substr(0, pth.lastIndexOf('_')) + path.extname(pth);
    file.beforeRev = path.join(dirname, beforeRev);
  }

  return file;
}
<commit_msg>add missing props to file mock for write() tests<commit_after>var path = require('path');
var assert = require('assert');
var sinon = require('sinon');
var gutil = require('gulp-util');
var proxyquire = require('proxyquire');
var fs = require('fs');
var del = sinon.stub().returns(Promise.resolve());
var write = proxyquire('../lib/write', { fs: fs, del: del });
var verbose = true;
var dirname = path.join(__dirname, '../');

describe('write()', function () {
  var fakeFileName;
  var fakeFilePath;

  beforeEach(function () {
    sinon.stub(fs, 'readFile');

    fakeFileName = 'app_d41d8cd98f.js';
    fakeFilePath = path.join('src', fakeFileName);
  });

  afterEach(function () {
    fs.readFile.restore();
    del.reset();
  });

  describe('with an invalid configuration', function () {
    it('should throw an error if output path is missing', function () {
      var stream = write(null, verbose);

      stream.on('error', function (err) {
        assert.equal(err.message, 'required argument "dest path" for revise.write() is missing');
      });

      stream.write(createFile(fakeFilePath));
    });
  });

  describe('with a valid configuration', function () {
    var stream;

    beforeEach(function () {
      stream = write('dist', verbose);
    });

    it('should push the original file and create the .rev', function () {
      var file = createFile(fakeFilePath);
      var filePath = file.path;
      var fileDir = path.dirname(filePath);
      var revFilePath = path.join(fileDir, 'app.js.rev');
      var pushedOriginalFile = false;

      stream.on('data', function (file) {
        if (pushedOriginalFile) {
          assert.equal(file.path, revFilePath);
          assert.equal(file.contents.toString(), fakeFileName);
          return;
        }

        pushedOriginalFile = true;
        assert.equal(file.path, filePath);
      });

      stream.write(file);
    });

    it('should ignore files that miss the beforeRev prop', function () {
      var spy = sinon.stub();

      stream.on('data', spy);
      stream.write(createFile('src/app.js', true));

      assert.equal(spy.callCount, 1);
    });

    it('should read the existing revision', function () {
      stream.write(createFile(fakeFilePath));

      assert.equal(fs.readFile.callCount, 1);
      assert.equal(fs.readFile.firstCall.args[0], path.join(dirname, 'dist', 'app.js.rev'));
    });

    it('should delete the old revision', function () {
      stream.write(createFile(fakeFilePath));
      fs.readFile.callArgWith(2, null, 'app_abcdef.js');

      assert.equal(del.callCount, 1);
      assert.deepEqual(del.firstCall.args, [
        [
          path.join(dirname, 'dist', 'app_abcdef.js'),
          path.join(dirname, 'dist', 'app_abcdef.js.map')
        ]
      ]);
    });

    it('should not delete the old revision if it\'s the same as the new one', function () {
      stream.write(createFile(fakeFilePath));
      fs.readFile.callArgWith(2, null, fakeFileName);

      assert.equal(del.callCount, 0);
    });
  });
});

function createFile (pth, omitBeforeRev) {
  var fullPath = path.join(dirname, pth);
  var pathDir = path.dirname(fullPath);
  var file = new gutil.File({
    cwd: dirname,
    base: pathDir,
    path: fullPath,
    contents: new Buffer('')
  });

  if (!omitBeforeRev) {
    file.beforeRev = fullPath.substr(0, fullPath.lastIndexOf('_')) + path.extname(fullPath);
  }

  return file;
}
<|endoftext|>


<commit_before>function URLify(s, num_chars) {
    // changes, e.g., "Petty theft" to "petty_theft"
    // remove all these words from the string before urlifying
    removelist = ["a", "an", "as", "at", "before", "but", "by", "for", "from",
                  "is", "in", "into", "like", "of", "off", "on", "onto", "per",
                  "since", "than", "the", "this", "that", "to", "up", "via",
                  "with"];
    r = new RegExp('\\b(' + removelist.join('|') + ')\\b', 'gi');
    s = s.replace(r, '');
    s = s.replace(/[^\w\s-]/g, '');  // remove unneeded chars
    s = s.replace(/^\s+|\s+$/g, ''); // trim leading/trailing spaces
    s = s.replace(/\s+/g, '_');      // convert spaces to underscores
    s = s.toLowerCase();             // convert to lowercase
    return s.substring(0, num_chars);// trim to first num_chars chars
}<commit_msg>Fixed #700 -- urlify.js now uses hyphens instead of underscores<commit_after>function URLify(s, num_chars) {
    // changes, e.g., "Petty theft" to "petty_theft"
    // remove all these words from the string before urlifying
    removelist = ["a", "an", "as", "at", "before", "but", "by", "for", "from",
                  "is", "in", "into", "like", "of", "off", "on", "onto", "per",
                  "since", "than", "the", "this", "that", "to", "up", "via",
                  "with"];
    r = new RegExp('\\b(' + removelist.join('|') + ')\\b', 'gi');
    s = s.replace(r, '');
    s = s.replace(/[^\w\s-]/g, '');  // remove unneeded chars
    s = s.replace(/^\s+|\s+$/g, ''); // trim leading/trailing spaces
    s = s.replace(/\s+/g, '-');      // convert spaces to hyphens
    s = s.toLowerCase();             // convert to lowercase
    return s.substring(0, num_chars);// trim to first num_chars chars
}<|endoftext|>


<commit_before>var slothifyjs = (function () {

    // setup slowload modifier callback, structure avoids some annoying timer/closure problems
    var slowloadModiferCallback = function (slowloadDiv, args) {

         return function () {

            (function (slowloadDiv, args) {

                // calculate new height
                var newHeight = parseInt(slowloadDiv.style.height.replace('px', '')) - args.loadIncrement;
                var newTop = parseInt(slowloadDiv.style.top.replace('px', '')) + args.loadIncrement;

                // check stopping conditions
                if (newHeight > 0 && newHeight > slowloadDiv.slothifyData.maxHeight) {

                    // update slowload div
                    slowloadDiv.style.height = newHeight + 'px';
                    slowloadDiv.style.top = newTop + 'px';

                    // create new update timeout
                    setTimeout(slowloadModiferCallback(slowloadDiv, args), args.loadSpeed);

                }

            })(slowloadDiv, args);

        };

    };

    var slothify = function (args) {

        return function () {

            var params = {

                loadMaxPercent: args.loadMaxPercent || 1.0, // max percentage to load images
                boxColor: args.boxColor || '#000000',       // color of box overlay
                loadSpeed: args.loadSpeed || 500,           // how often in ms to pass
                loadIncrement: args.loadIncrement || 1      // pixels to load per pass

            };

            // loop through images and make them slow
            var imgs = document.getElementsByTagName('img');
            for(var i = 0; i < imgs.length; i++) {

                // get some things we need
                var img = imgs[i],
                    parent = img.parentNode,
                    slowload = document.createElement('DIV');

                // set up initial state of box
                slowload.className = 'sloth-box';
                slowload.style.backgroundColor = params.boxColor;
                slowload.style.width = img.width;
                slowload.style.height = img.height;
                slowload.style.position = 'absolute';
                slowload.style.top = img.offsetTop;
                slowload.style.left = img.offsetLeft;

                // remember what the max height should be for later calculation
                slowload.slothifyData = {
                    maxHeight: img.height * (1.0 - params.loadMaxPercent)
                };

                // put box over image
                parent.appendChild(slowload);

                // slowload using timeout since this is nicer to the browser :)
                setTimeout(slowloadModiferCallback(slowload, params), params.loadSpeed);

            }

        }

    };

    return {

        fixMyImagesLoadingSoFast: slothify

    };

})();<commit_msg>Fixed math for 100% image load<commit_after>var slothifyjs = (function () {

    // setup slowload modifier callback, structure avoids some annoying timer/closure problems
    var slowloadModiferCallback = function (slowloadDiv, args) {

         return function () {

            (function (slowloadDiv, args) {

                // calculate new height
                var currHeight = parseInt(slowloadDiv.style.height.replace('px', '')),
                    currTop = parseInt(slowloadDiv.style.top.replace('px', '')),
                    inc = currHeight - args.loadIncrement <= slowloadDiv.slothifyData.maxHeight
                            ? currHeight - slowloadDiv.slothifyData.maxHeight : args.loadIncrement,
                    newHeight = currHeight - inc,
                    newTop = currTop + inc;

                    // update slowload div
                    slowloadDiv.style.height = newHeight + 'px';
                    slowloadDiv.style.top = newTop + 'px';

                // check stopping conditions
                if (newHeight > slowloadDiv.slothifyData.maxHeight) {

                    // create new update timeout
                    setTimeout(slowloadModiferCallback(slowloadDiv, args), args.loadSpeed);

                }

            })(slowloadDiv, args);

        };

    };

    var slothify = function (args) {

        return function () {

            var params = {

                loadMaxPercent: args.loadMaxPercent || 1.0, // max percentage to load images
                boxColor: args.boxColor || '#000000',       // color of box overlay
                loadSpeed: args.loadSpeed || 500,           // how often in ms to pass
                loadIncrement: args.loadIncrement || 1      // pixels to load per pass

            };

            // loop through images and make them slow
            var imgs = document.getElementsByTagName('img');
            for(var i = 0; i < imgs.length; i++) {

                // get some things we need
                var img = imgs[i],
                    parent = img.parentNode,
                    slowload = document.createElement('DIV');

                // set up initial state of box
                slowload.className = 'sloth-box';
                slowload.style.backgroundColor = params.boxColor;
                slowload.style.width = img.width;
                slowload.style.height = img.height;
                slowload.style.position = 'absolute';
                slowload.style.top = img.offsetTop;
                slowload.style.left = img.offsetLeft;

                // remember what the max height should be for later calculation
                slowload.slothifyData = {
                    maxHeight: img.height * (1.0 - params.loadMaxPercent)
                };

                // put box over image
                parent.appendChild(slowload);

                // slowload using timeout since this is nicer to the browser :)
                setTimeout(slowloadModiferCallback(slowload, params), params.loadSpeed);

            }

        }

    };

    return {

        fixMyImagesLoadingSoFast: slothify

    };

})();<|endoftext|>