<commit_before>// I18N constants
// LANG: "de", ENCODING: UTF-8

{
  "Bold": "Fett",
  "Italic": "Kursiv",
  "Underline": "Unterstrichen",
  "Strikethrough": "Durchgestrichen",
  "Subscript": "Tiefgestellt",
  "Superscript": "Hochgestellt",
  "Justify Left": "Linksbündig",
  "Justify Center": "Zentriert",
  "Justify Right": "Rechtsbündig",
  "Justify Full": "Blocksatz",
  "Ordered List": "Nummerierte Liste",
  "Bulleted List": "Aufzählungsliste",
  "Decrease Indent": "Einzug verkleinern",
  "Increase Indent": "Einzug vergrößern",
  "Font Color": "Schriftfarbe",
  "Background Color": "Hindergrundfarbe",
  "Horizontal Rule": "Horizontale Linie",
  "Insert Web Link": "Hyperlink einfügen",
  "Insert/Modify Image": "Bild einfügen/verändern",
  "Insert Table": "Tabelle einfügen",
  "Toggle HTML Source": "HTML Quelltext ein/ausschalten",
  "Enlarge Editor": "Editor vergrößern",
  "About this editor": "Über diesen Editor",
  "Help using editor": "Hilfe",
  "Current style": "Derzeitiger Stil",
  "Undoes your last action": "Rückgängig",
  "Redoes your last action": "Wiederholen",
  "Cut selection": "Ausschneiden",
  "Copy selection": "Kopieren",
  "Paste from clipboard": "Einfügen aus der Zwischenablage",
  "Direction left to right": "Textrichtung von Links nach Rechts",
  "Direction right to left": "Textrichtung von Rechts nach Links",
  "Remove formatting": "Formatierung entfernen",
  "Select all": "Alles markieren",
  "Print document": "Dokument ausdrucken",
  "Clear MSOffice tags": "MSOffice filter",
  "Clear Inline Font Specifications": "Zeichensatz Formatierungen entfernen",
  "Split Block": "Block teilen",
  "Toggle Borders": "Tabellenränder ein/ausblenden",
  "Save as": "speichern unter",
  "Insert/Overwrite": "Einfügen/Überschreiben",
  "— format —": "— Format —",
  "Heading 1": "Überschrift 1",
  "Heading 2": "Überschrift 2",
  "Heading 3": "Überschrift 3",
  "Heading 4": "Überschrift 4",
  "Heading 5": "Überschrift 5",
  "Heading 6": "Überschrift 6",
  "Normal": "Normal (Absatz)",
  "Address": "Adresse",
  "Formatted": "Formatiert",

  //dialogs
  "OK": "OK",
  "Cancel": "Abbrechen",
  "Path": "Pfad",
  "You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG.": "Sie sind im Text-Modus. Benutzen Sie den [<>] Button, um in den visuellen Modus (WYSIWIG) zu gelangen.",
  "The Paste button does not work in Mozilla based web browsers (technical security reasons). Press CTRL-V on your keyboard to paste directly.": "Aus Sicherheitsgründen dürfen Skripte normalerweise nicht auf Ausschneiden/Kopieren/Einfügen zugreifen. Bitte klicken Sie OK um die technische Erläuterung auf mozilla.org zu öffnen, in der erklärt wird, wie einem Skript Zugriff gewährt werden kann.",

  "You need to select some text before create a link": "Sie müssen einen Text markieren, um einen Link zu erstellen",
  "Your Document is not well formed. Check JavaScript console for details.": "Ihr Dokument ist in keinem sauberen Format. Benutzen Sie die Javascript Console für weitere Informationen.",

  "Alignment:": "Ausrichtung:",
  "Not set": "nicht eingestellt",
  "Left": "links",
  "Right": "rechts",
  "Texttop": "oben bündig",
  "Absmiddle": "mittig",
  "Baseline": "Grundlinie",
  "Absbottom": "unten bündig",
  "Bottom": "unten",
  "Middle": "zentriert",
  "Top": "oben",

  "Layout": "Layout",
  "Spacing": "Abstand",
  "Horizontal:": "horizontal:",
  "Horizontal padding": "horizontaler Inhaltsabstand",
  "Vertical:": "vertikal:",
  "Vertical padding": "vertikaler Inhaltsabstand",
  "Border thickness:": "Randstärke:",
  "Leave empty for no border": "leer lassen für keinen Rand",

  //Insert Link
  "Insert/Modify Link": "Verknüpfung hinzufügen/ändern",
  "None (use implicit)": "k.A. (implizit)",
  "New window (_blank)": "Neues Fenster (_blank)",
  "Same frame (_self)": "Selber Rahmen (_self)",
  "Top frame (_top)": "Oberster Rahmen (_top)",
  "Other": "Anderes",
  "Target:": "Ziel:",
  "Title (tooltip):": "Titel (Tooltip):",
  "URL:": "URL:",
  "You must enter the URL where this link points to": "Sie müssen eine Ziel-URL angeben für die Verknüpfung angeben",

  // Insert Table
  "Insert Table": "Table einfügen",
  "Rows:": "Zeilen:",
  "Number of rows": "Zeilenanzahl",
  "Cols:": "Spalten:",
  "Number of columns": "Spaltenanzahl",
  "Width:": "Breite:",
  "Width of the table": "Tabellenbreite",
  "Percent": "Prozent",
  "Pixels": "Pixel",
  "Em": "Geviert",
  "Width unit": "Größeneinheit",
  "Fixed width columns": "Spalten mit fester Breite",
  "Positioning of this table": "Positionierung der Tabelle",
  "Cell spacing:": "Zellenabstand:",
  "Space between adjacent cells": "Raum zwischen angrenzenden Zellen",
  "Cell padding:": "Innenabstand:",
  "Space between content and border in cell": "Raum zwischen Inhalt und Rand der Zelle",
  "You must enter a number of rows": "Bitte geben Sie die Anzahl der Zeilen an",
  "You must enter a number of columns": "Bitte geben Sie die Anzahl der Spalten an",

  // Insert Image
  "Insert Image": "Bild einfügen",
  "Image URL:": "Bild URL:",
  "Enter the image URL here": "Bitte geben sie hier die Bild URL ein",
  "Preview": "Voransicht",
  "Preview the image in a new window": "Voransicht des Bildes in einem neuen Fenster",
  "Alternate text:": "Alternativer Text:",
  "For browsers that don't support images": "für Browser, die keine Bilder unterstützen",
  "Positioning of this image": "Positionierung dieses Bildes",
  "Image Preview:": "Bild Voransicht:",
  "You must enter the URL": "Bitte geben Sie die URL ein",

  "button_bold": "de/bold.gif",
  "button_italic": "de/italic.gif",
  "button_underline": "de/underline.gif",

  // Editor Help
  "Keyboard shortcuts": "Tastaturkürzel",
  "The editor provides the following key combinations:": "Der Editor unterstützt die folgenden kombinationen:",
  "new paragraph": "Neuer Absatz(Paragraph)",
  "insert linebreak": "Harter Umbruch einfügen",
  "Set format to paragraph": "Setze Formatierung auf Absatz",
  "Clean content pasted from Word": "Von Word eingefügter Text bereinigen",
  "Headings": "Überschrift Typ 1 bis 6",
  "Close": "Schließen"
};<commit_msg>Changeset 373 Add German translations for the remove inline font confirm boxes<commit_after>// I18N constants
// LANG: "de", ENCODING: UTF-8

{
  "Bold": "Fett",
  "Italic": "Kursiv",
  "Underline": "Unterstrichen",
  "Strikethrough": "Durchgestrichen",
  "Subscript": "Tiefgestellt",
  "Superscript": "Hochgestellt",
  "Justify Left": "Linksbündig",
  "Justify Center": "Zentriert",
  "Justify Right": "Rechtsbündig",
  "Justify Full": "Blocksatz",
  "Ordered List": "Nummerierte Liste",
  "Bulleted List": "Aufzählungsliste",
  "Decrease Indent": "Einzug verkleinern",
  "Increase Indent": "Einzug vergrößern",
  "Font Color": "Schriftfarbe",
  "Background Color": "Hindergrundfarbe",
  "Horizontal Rule": "Horizontale Linie",
  "Insert Web Link": "Hyperlink einfügen",
  "Insert/Modify Image": "Bild einfügen/verändern",
  "Insert Table": "Tabelle einfügen",
  "Toggle HTML Source": "HTML Quelltext ein/ausschalten",
  "Enlarge Editor": "Editor vergrößern",
  "About this editor": "Über diesen Editor",
  "Help using editor": "Hilfe",
  "Current style": "Derzeitiger Stil",
  "Undoes your last action": "Rückgängig",
  "Redoes your last action": "Wiederholen",
  "Cut selection": "Ausschneiden",
  "Copy selection": "Kopieren",
  "Paste from clipboard": "Einfügen aus der Zwischenablage",
  "Direction left to right": "Textrichtung von Links nach Rechts",
  "Direction right to left": "Textrichtung von Rechts nach Links",
  "Remove formatting": "Formatierung entfernen",
  "Select all": "Alles markieren",
  "Print document": "Dokument ausdrucken",
  "Clear MSOffice tags": "MSOffice filter",
  "Clear Inline Font Specifications": "Zeichensatz Formatierungen entfernen",
  "Would you like to clear font typefaces?": "Wollen Sie Zeichensatztypen entfernen",
  "Would you like to clear font sizes?": "Wollen Sie Zeichensatzgrößen entfernen",
  "Would you like to clear font colours?": "Wollen sie Zeichensatzfarben entfernen",
  "Split Block": "Block teilen",
  "Toggle Borders": "Tabellenränder ein/ausblenden",
  "Save as": "speichern unter",
  "Insert/Overwrite": "Einfügen/Überschreiben",
  "— format —": "— Format —",
  "Heading 1": "Überschrift 1",
  "Heading 2": "Überschrift 2",
  "Heading 3": "Überschrift 3",
  "Heading 4": "Überschrift 4",
  "Heading 5": "Überschrift 5",
  "Heading 6": "Überschrift 6",
  "Normal": "Normal (Absatz)",
  "Address": "Adresse",
  "Formatted": "Formatiert",

  //dialogs
  "OK": "OK",
  "Cancel": "Abbrechen",
  "Path": "Pfad",
  "You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG.": "Sie sind im Text-Modus. Benutzen Sie den [<>] Button, um in den visuellen Modus (WYSIWIG) zu gelangen.",
  "The Paste button does not work in Mozilla based web browsers (technical security reasons). Press CTRL-V on your keyboard to paste directly.": "Aus Sicherheitsgründen dürfen Skripte normalerweise nicht auf Ausschneiden/Kopieren/Einfügen zugreifen. Bitte klicken Sie OK um die technische Erläuterung auf mozilla.org zu öffnen, in der erklärt wird, wie einem Skript Zugriff gewährt werden kann.",

  "You need to select some text before create a link": "Sie müssen einen Text markieren, um einen Link zu erstellen",
  "Your Document is not well formed. Check JavaScript console for details.": "Ihr Dokument ist in keinem sauberen Format. Benutzen Sie die Javascript Console für weitere Informationen.",

  "Alignment:": "Ausrichtung:",
  "Not set": "nicht eingestellt",
  "Left": "links",
  "Right": "rechts",
  "Texttop": "oben bündig",
  "Absmiddle": "mittig",
  "Baseline": "Grundlinie",
  "Absbottom": "unten bündig",
  "Bottom": "unten",
  "Middle": "zentriert",
  "Top": "oben",

  "Layout": "Layout",
  "Spacing": "Abstand",
  "Horizontal:": "horizontal:",
  "Horizontal padding": "horizontaler Inhaltsabstand",
  "Vertical:": "vertikal:",
  "Vertical padding": "vertikaler Inhaltsabstand",
  "Border thickness:": "Randstärke:",
  "Leave empty for no border": "leer lassen für keinen Rand",

  //Insert Link
  "Insert/Modify Link": "Verknüpfung hinzufügen/ändern",
  "None (use implicit)": "k.A. (implizit)",
  "New window (_blank)": "Neues Fenster (_blank)",
  "Same frame (_self)": "Selber Rahmen (_self)",
  "Top frame (_top)": "Oberster Rahmen (_top)",
  "Other": "Anderes",
  "Target:": "Ziel:",
  "Title (tooltip):": "Titel (Tooltip):",
  "URL:": "URL:",
  "You must enter the URL where this link points to": "Sie müssen eine Ziel-URL angeben für die Verknüpfung angeben",

  // Insert Table
  "Insert Table": "Table einfügen",
  "Rows:": "Zeilen:",
  "Number of rows": "Zeilenanzahl",
  "Cols:": "Spalten:",
  "Number of columns": "Spaltenanzahl",
  "Width:": "Breite:",
  "Width of the table": "Tabellenbreite",
  "Percent": "Prozent",
  "Pixels": "Pixel",
  "Em": "Geviert",
  "Width unit": "Größeneinheit",
  "Fixed width columns": "Spalten mit fester Breite",
  "Positioning of this table": "Positionierung der Tabelle",
  "Cell spacing:": "Zellenabstand:",
  "Space between adjacent cells": "Raum zwischen angrenzenden Zellen",
  "Cell padding:": "Innenabstand:",
  "Space between content and border in cell": "Raum zwischen Inhalt und Rand der Zelle",
  "You must enter a number of rows": "Bitte geben Sie die Anzahl der Zeilen an",
  "You must enter a number of columns": "Bitte geben Sie die Anzahl der Spalten an",

  // Insert Image
  "Insert Image": "Bild einfügen",
  "Image URL:": "Bild URL:",
  "Enter the image URL here": "Bitte geben sie hier die Bild URL ein",
  "Preview": "Voransicht",
  "Preview the image in a new window": "Voransicht des Bildes in einem neuen Fenster",
  "Alternate text:": "Alternativer Text:",
  "For browsers that don't support images": "für Browser, die keine Bilder unterstützen",
  "Positioning of this image": "Positionierung dieses Bildes",
  "Image Preview:": "Bild Voransicht:",
  "You must enter the URL": "Bitte geben Sie die URL ein",

  "button_bold": "de/bold.gif",
  "button_italic": "de/italic.gif",
  "button_underline": "de/underline.gif",

  // Editor Help
  "Keyboard shortcuts": "Tastaturkürzel",
  "The editor provides the following key combinations:": "Der Editor unterstützt die folgenden kombinationen:",
  "new paragraph": "Neuer Absatz(Paragraph)",
  "insert linebreak": "Harter Umbruch einfügen",
  "Set format to paragraph": "Setze Formatierung auf Absatz",
  "Clean content pasted from Word": "Von Word eingefügter Text bereinigen",
  "Headings": "Überschrift Typ 1 bis 6",
  "Close": "Schließen"
};<|endoftext|>


<commit_before>import { createSelector } from 'reselect'
import get from 'lodash/get'
import { selectParamsUsername } from './params'

const POST_DETAIL_EXPRESSION = /^\/[\w-]+\/post\/.+/

const AUTHENTICATION_ROUTES = [
  /^\/enter\b/,
  /^\/forgot-password\b/,
  /^\/auth\/reset-my-password\b/,
  /^\/join\b/,
  /^\/signup\b/,
]

// props.routing.xxx
export const selectPropsLocationKey = (state, props) => get(props, 'location.key')
export const selectPropsPathname = (state, props) => get(props, 'location.pathname')
export const selectPropsQueryTerms = (state, props) => get(props, 'location.query.terms')
export const selectPropsQueryType = (state, props) => get(props, 'location.query.type')
export const selectPropsQueryBefore = (state, props) => get(props, 'location.query.before')

// state.routing.xxx
export const selectLocation = state => state.routing.get('location')
export const selectPreviousPath = state => state.routing.get('previousPath')

// state.routing.location.xxx
export const selectPathname = state => state.routing.getIn(['location', 'pathname'])
export const selectQueryTerms = state => state.routing.getIn(['location', 'terms'])
export const selectQueryPreview = state => state.routing.getIn(['location', 'preview'])
export const selectQueryBefore = state => state.routing.getIn(['location', 'before'])
export const selectSubmissionType = state => state.routing.getIn(['location', 'submissionType'])

// props.routing for discover streams
export function selectDiscoverStream(state, { params: { stream } }) {
  if (!stream || stream === 'recent' || stream === 'trending' || stream === 'shop') {
    return 'global'
  }
  return stream
}
export function selectDiscoverStreamKind(state, { params: { stream, kind } }) {
  if (!kind && !stream) { return 'featured' }
  if (stream === 'recent' || stream === 'trending' || stream === 'shop') { return stream }
  if (!kind) { return 'featured' }
  return kind
}

// Memoized selectors
export const selectViewNameFromRoute = createSelector(
  [selectPathname, selectParamsUsername], (pathname, username) => {
    if (pathname === '/') {
      return 'editorial'
    }
    if (/^\/following\b/.test(pathname)) {
      return 'following'
    }
    if (/^\/find\b|^\/search\b/.test(pathname)) {
      return 'search'
    }
    if (/^\/discover\/all\b/.test(pathname)) {
      return 'discoverAll'
    }
    if (/^\/discover\b/.test(pathname)) {
      return 'discover'
    }
    if (/^\/invitations\b/.test(pathname)) {
      return 'invitations'
    }
    if (/^\/settings\b/.test(pathname)) {
      return 'settings'
    }
    if (/^\/notifications\b/.test(pathname)) {
      return 'notifications'
    }
    if (/^\/onboarding\b/.test(pathname)) {
      return 'onboarding'
    }
    if (POST_DETAIL_EXPRESSION.test(pathname)) {
      return 'postDetail'
    }
    if (AUTHENTICATION_ROUTES.some(route => route.test(pathname))) {
      return 'authentication'
    }
    // Yo! to get 'userDetail' you have to pass in props... for now
    if (username) {
      return 'userDetail'
    }
    return 'unknown'
  },
)

export const selectIsAuthenticationView = createSelector(
  [selectViewNameFromRoute], viewName => viewName === 'authentication',
)

export const selectIsOnboardingView = createSelector(
  [selectViewNameFromRoute], viewName => viewName === 'onboarding',
)

export const selectIsPostDetail = createSelector(
  [selectViewNameFromRoute], viewName => viewName === 'postDetail',
)

export const selectIsGlobalRoot = createSelector(
  [selectPathname], pathname => /^\/(?:discover(\/featured|\/recommended|\/trending|\/recent|\/shop)?)?$/.test(pathname),
)

export const selectIsSubscribedRoot = createSelector(
  [selectPathname], pathname => /^\/(?:discover\/subscribed(\/trending|\/shop|\/recent)?)?$/.test(pathname),
)

export const selectShowCategoryHeader = createSelector(
  [selectIsGlobalRoot, selectIsSubscribedRoot], (isGlobalRoot, isSubscribedRoot) =>
    isGlobalRoot || isSubscribedRoot,
)
<commit_msg>fix pathname check for AUTH_ROUTES<commit_after>import { createSelector } from 'reselect'
import get from 'lodash/get'
import { selectParamsUsername } from './params'

const POST_DETAIL_EXPRESSION = /^\/[\w-]+\/post\/.+/

const AUTHENTICATION_ROUTES = [
  /^\/enter(\/|$)/,
  /^\/forgot-password(\/|$)/,
  /^\/auth\/reset-my-password(\/|$)/,
  /^\/join(\/|$)/,
  /^\/signup(\/|$)/,
]

// props.routing.xxx
export const selectPropsLocationKey = (state, props) => get(props, 'location.key')
export const selectPropsPathname = (state, props) => get(props, 'location.pathname')
export const selectPropsQueryTerms = (state, props) => get(props, 'location.query.terms')
export const selectPropsQueryType = (state, props) => get(props, 'location.query.type')
export const selectPropsQueryBefore = (state, props) => get(props, 'location.query.before')

// state.routing.xxx
export const selectLocation = state => state.routing.get('location')
export const selectPreviousPath = state => state.routing.get('previousPath')

// state.routing.location.xxx
export const selectPathname = state => state.routing.getIn(['location', 'pathname'])
export const selectQueryTerms = state => state.routing.getIn(['location', 'terms'])
export const selectQueryPreview = state => state.routing.getIn(['location', 'preview'])
export const selectQueryBefore = state => state.routing.getIn(['location', 'before'])
export const selectSubmissionType = state => state.routing.getIn(['location', 'submissionType'])

// props.routing for discover streams
export function selectDiscoverStream(state, { params: { stream } }) {
  if (!stream || stream === 'recent' || stream === 'trending' || stream === 'shop') {
    return 'global'
  }
  return stream
}
export function selectDiscoverStreamKind(state, { params: { stream, kind } }) {
  if (!kind && !stream) { return 'featured' }
  if (stream === 'recent' || stream === 'trending' || stream === 'shop') { return stream }
  if (!kind) { return 'featured' }
  return kind
}

// Memoized selectors
export const selectViewNameFromRoute = createSelector(
  [selectPathname, selectParamsUsername], (pathname, username) => {
    if (pathname === '/') {
      return 'editorial'
    }
    if (/^\/following\b/.test(pathname)) {
      return 'following'
    }
    if (/^\/find\b|^\/search\b/.test(pathname)) {
      return 'search'
    }
    if (/^\/discover\/all\b/.test(pathname)) {
      return 'discoverAll'
    }
    if (/^\/discover\b/.test(pathname)) {
      return 'discover'
    }
    if (/^\/invitations\b/.test(pathname)) {
      return 'invitations'
    }
    if (/^\/settings\b/.test(pathname)) {
      return 'settings'
    }
    if (/^\/notifications\b/.test(pathname)) {
      return 'notifications'
    }
    if (/^\/onboarding\b/.test(pathname)) {
      return 'onboarding'
    }
    if (POST_DETAIL_EXPRESSION.test(pathname)) {
      return 'postDetail'
    }
    if (AUTHENTICATION_ROUTES.some(route => route.test(pathname))) {
      return 'authentication'
    }
    // Yo! to get 'userDetail' you have to pass in props... for now
    if (username) {
      return 'userDetail'
    }
    return 'unknown'
  },
)

export const selectIsAuthenticationView = createSelector(
  [selectViewNameFromRoute], viewName => viewName === 'authentication',
)

export const selectIsOnboardingView = createSelector(
  [selectViewNameFromRoute], viewName => viewName === 'onboarding',
)

export const selectIsPostDetail = createSelector(
  [selectViewNameFromRoute], viewName => viewName === 'postDetail',
)

export const selectIsGlobalRoot = createSelector(
  [selectPathname], pathname => /^\/(?:discover(\/featured|\/recommended|\/trending|\/recent|\/shop)?)?$/.test(pathname),
)

export const selectIsSubscribedRoot = createSelector(
  [selectPathname], pathname => /^\/(?:discover\/subscribed(\/trending|\/shop|\/recent)?)?$/.test(pathname),
)

export const selectShowCategoryHeader = createSelector(
  [selectIsGlobalRoot, selectIsSubscribedRoot], (isGlobalRoot, isSubscribedRoot) =>
    isGlobalRoot || isSubscribedRoot,
)
<|endoftext|>


<commit_before>import m from 'mithril';
import moment from 'moment';
import _ from 'underscore';
import I18n from 'i18n-js';
import h from '../h';
import projectDashboardMenu from '../c/project-dashboard-menu';
import projectInviteCard from '../c/project-invite-card';
import projectGoalsBoxDashboard from './project-goals-box-dashboard';
import projectGoalsVM from '../vms/project-goals-vm';
import userVM from '../vms/user-vm.js';

const I18nScope = _.partial(h.i18nScope, 'projects.insights');

const projectInsightsSub = {
    controller(args) {
        const filtersVM = args.filtersVM;

        projectGoalsVM.fetchGoals(filtersVM.project_id());
        const balanceLoader = userVM.getUserBalance(args.project.user_id);

        return {
            projectGoalsVM,
            balanceLoader
        };
    },
    view(ctrl, args) {
        const project = args.project,
            subscribersDetails = args.subscribersDetails,
            balanceData = (ctrl.balanceLoader() && !_.isNull(_.first(ctrl.balanceLoader())) ? _.first(ctrl.balanceLoader()) : null);

        return m('.project-insights', !args.l() ? [
            m(`.w-section.section-product.${project.mode}`),
            (project.is_owner_or_admin ? m.component(projectDashboardMenu, {
                project: m.prop(project)
            }) : ''),
            m('.dashboard-header.section-one-column', [
                m('.u-marginbottom-30.u-text-center', [
                    m('.fontsize-larger.fontweight-semibold',
                        `Olá, ${project.user.public_name || project.user.name}!`
                    ),
                    m('.fontsize-smaller',
                        `Este é o retrato de sua campanha hoje, ${moment().format('DD [de] MMMM [de] YYYY')}`
                    )
                ]),
                m('.w-container',
                    m('.flex-row.u-marginbottom-40.u-text-center-small-only', [
                        subscribersDetails && !_.isEmpty(ctrl.projectGoalsVM.goals()) ?
                        m.component(projectGoalsBoxDashboard, { goalDetails: ctrl.projectGoalsVM.goals, amount: subscribersDetails.amount_paid_for_valid_period }) : '',
                        m('.card.card-terciary.flex-column.u-marginbottom-10.u-radius', [
                            m('.fontsize-small.u-marginbottom-10',
                                'Assinantes ativos'
                            ),
                            m('.fontsize-largest.fontweight-semibold',
                                subscribersDetails.total_subscriptions
                            )
                        ]),
                        m('.card.card-terciary.flex-column.u-marginbottom-10.u-radius', [
                            m('.fontsize-small.u-marginbottom-10',
                                'Receita Mensal'
                            ),
                            m('.fontsize-largest.fontweight-semibold',
                                `R$${h.formatNumber(subscribersDetails.amount_paid_for_valid_period, 2, 3)}`
                            )
                        ]),
                        m('.card.flex-column.u-marginbottom-10.u-radius', [
                            m('.fontsize-small.u-marginbottom-10', [
                                'Saldo',
                                m.trust(' '),
                                ' ',
                                m(`a.btn-inline.btn-terciary.fontsize-smallest.u-radius[href='/users/${project.user_id}/edit#balance']`,
                                    'Sacar'
                                )
                            ]),
                            m('.fontsize-largest.fontweight-semibold.text-success.u-marginbottom-10',
                                (balanceData && balanceData.amount ? `R$${h.formatNumber(balanceData.amount, 2, 3)}` : '')
                            )
                        ])
                    ])
                ),
                (project.state === 'online' && !project.has_cancelation_request ? m('.w-container', m.component(projectInviteCard, {
                    project
                })) : ''),
            ])
        ] : h.loader());
    }
};

export default projectInsightsSub;
<commit_msg>Delay on updating the balance warning<commit_after>import m from 'mithril';
import moment from 'moment';
import _ from 'underscore';
import I18n from 'i18n-js';
import h from '../h';
import projectDashboardMenu from '../c/project-dashboard-menu';
import projectInviteCard from '../c/project-invite-card';
import projectGoalsBoxDashboard from './project-goals-box-dashboard';
import projectGoalsVM from '../vms/project-goals-vm';
import userVM from '../vms/user-vm.js';

const I18nScope = _.partial(h.i18nScope, 'projects.insights');

const projectInsightsSub = {
    controller(args) {
        const filtersVM = args.filtersVM;

        projectGoalsVM.fetchGoals(filtersVM.project_id());
        const balanceLoader = userVM.getUserBalance(args.project.user_id);

        return {
            projectGoalsVM,
            balanceLoader
        };
    },
    view(ctrl, args) {
        const project = args.project,
            subscribersDetails = args.subscribersDetails,
            balanceData = (ctrl.balanceLoader() && !_.isNull(_.first(ctrl.balanceLoader())) ? _.first(ctrl.balanceLoader()) : null);

        return m('.project-insights', !args.l() ? [
            m(`.w-section.section-product.${project.mode}`),
            (project.is_owner_or_admin ? m.component(projectDashboardMenu, {
                project: m.prop(project)
            }) : ''),
            m('.dashboard-header.section-one-column', [
                m('.u-marginbottom-30.u-text-center', [
                    m('.fontsize-larger.fontweight-semibold',
                        `Olá, ${project.user.public_name || project.user.name}!`
                    ),
                    m('.fontsize-smaller',
                        `Este é o retrato de sua campanha hoje, ${moment().format('DD [de] MMMM [de] YYYY')}`
                    )
                ]),
                m('.w-container',
                    m('.flex-row.u-marginbottom-40.u-text-center-small-only', [
                        subscribersDetails && !_.isEmpty(ctrl.projectGoalsVM.goals()) ?
                        m.component(projectGoalsBoxDashboard, { goalDetails: ctrl.projectGoalsVM.goals, amount: subscribersDetails.amount_paid_for_valid_period }) : '',
                        m('.card.card-terciary.flex-column.u-marginbottom-10.u-radius', [
                            m('.fontsize-small.u-marginbottom-10',
                                'Assinantes ativos'
                            ),
                            m('.fontsize-largest.fontweight-semibold',
                                subscribersDetails.total_subscriptions
                            )
                        ]),
                        m('.card.card-terciary.flex-column.u-marginbottom-10.u-radius', [
                            m('.fontsize-small.u-marginbottom-10',
                                'Receita Mensal'
                            ),
                            m('.fontsize-largest.fontweight-semibold',
                                `R$${h.formatNumber(subscribersDetails.amount_paid_for_valid_period, 2, 3)}`
                            )
                        ]),
                        m('.card.flex-column.u-marginbottom-10.u-radius', [
                            m('.fontsize-small.u-marginbottom-10', [
                                'Saldo',
                                m.trust(' '),
                                ' ',
                                m(`a.btn-inline.btn-terciary.fontsize-smallest.u-radius[href='/users/${project.user_id}/edit#balance']`,
                                    'Sacar'
                                )
                            ]),
                            m('.fontsize-largest.fontweight-semibold.text-success.u-marginbottom-10',
                                (balanceData && balanceData.amount ? `R$${h.formatNumber(balanceData.amount, 2, 3)}` : '')
                            ),
                            m('.fontsize-mini.fontcolor-secondary.lineheight-tighter',
                                'O saldo demora até 20 mins após o pagamento para ser atualizado.'
                            )
                        ])
                    ])
                ),
                (project.state === 'online' && !project.has_cancelation_request ? m('.w-container', m.component(projectInviteCard, {
                    project
                })) : ''),
            ])
        ] : h.loader());
    }
};

export default projectInsightsSub;
<|endoftext|>


<commit_before>#!/usr/bin/env node

exports.command = {
  description: 'run a command in each project directory',
  arguments: '<command>'
};

if (require.main !== module) {
  return;
}

var chalk = require('chalk');
var spawn = require('child_process').spawn;
var split = require('split');
var _ = require('lodash');

_.str = require('underscore.string');

var storage = require('../lib/storage.js');
var utilities = require('../lib/utilities.js');

var program = utilities.programDefaults('each', '<command>');

program.option('-s, --stdout', 'run commands in our stdout');

program.option('-n, --no-headers',
  'suppress the headers shown for each project');

program.option('-w, --warnings', 'warn on missing directories or directories ' +
  'that are actually files');

program.parse(process.argv);
program.handleColor();

var command = program.args[0];

var spawnOptions = {};

if (program.stdout) {
  spawnOptions.stdio = 'inherit';
}

function trimArray(array) {
  var start = _.findIndex(array);
  var end = _.findLastIndex(array);

  if (start === -1) {
    return [];
  }

  return array.slice(start, end + 1);
}

storage.setup(function () {
  var projects = storage.allWithDirectory();

  var longestName = _.max(projects,
    function (project) { return project.name.length; }).name.length + 2;

  var directories = new utilities.DirectoryEmitter(projects);

  directories.on('directory', function (directory, project) {
    // TODO: Make less OS X/Ubuntu/bash-centric
    var bash = spawn('bash', ['-c', command],
      _.extend(spawnOptions, { cwd: directory }));

    if (program.stdout) {
      bash.on('close', process.exit);
    } else {
      var lines = [];

      bash.stdout.pipe(split()).on('data', function (line) {
        lines.push(line);
      });

      // We display things one of three ways--if there was only one line of
      // output we print it on the same line as the project name; if there was
      // more than one line we print it underneath, and if there were no lines
      // of output we print the project name in yellow.
      bash.on('close', function () {
        lines = trimArray(lines);

        if (lines.length > 1) {
          console.log(chalk.green(project.name));
        } else {
          if (lines.length) {
            process.stdout.write(chalk.green(_.str.rpad(project.name + ':',
              longestName)));
          } else {
            console.log(chalk.yellow(_.str.rpad(project.name), longestName));
          }
        }

        if (lines.length) {
          console.log(lines.join('\n'));
        }

        if (lines.length > 1) {
          console.log();
        }
      });
    }
  });

  if (program.warnings) {
    directories.on('missing', function (directory) {
      console.warn(chalk.yellow(directory, 'is missing.'));
    });

    directories.on('file', function (directory) {
      console.warn(chalk.yellow(directory, 'is a file, not a directory.'));
    });
  }

  directories.on('error', function (err) {
    console.error('Error:', err);

    process.exit(1);
  });
});
<commit_msg>Implement --no-headers, add PROJECT env<commit_after>#!/usr/bin/env node

exports.command = {
  description: 'run a command in each project directory',
  arguments: '<command>'
};

if (require.main !== module) {
  return;
}

var chalk = require('chalk');
var spawn = require('child_process').spawn;
var split = require('split');
var _ = require('lodash');

_.str = require('underscore.string');

var storage = require('../lib/storage.js');
var utilities = require('../lib/utilities.js');

var program = utilities.programDefaults('each', '<command>');

program.option('-s, --stdout', 'run commands in our stdout');

program.option('-n, --no-headers',
  'suppress the headers shown for each project');

program.option('-w, --warnings', 'warn on missing directories or directories ' +
  'that are actually files');

program.option('-i, --ignore-empty-output',
  "don't display projects with no output");

program.parse(process.argv);
program.handleColor();

var command = program.args[0];

var spawnOptions = {};

if (program.stdout) {
  spawnOptions.stdio = 'inherit';
}

function trimArray(array) {
  var start = _.findIndex(array);
  var end = _.findLastIndex(array);

  if (start === -1) {
    return [];
  }

  return array.slice(start, end + 1);
}

storage.setup(function () {
  var projects = storage.allWithDirectory();

  var longestName = _.max(projects,
    function (project) { return project.name.length; }).name.length + 2;

  var directories = new utilities.DirectoryEmitter(projects);

  directories.on('directory', function (directory, project) {
    // TODO: Make less OS X/Ubuntu/bash-centric
    var bash = spawn('bash', ['-c', command],
      _.extend(spawnOptions, {
        cwd: directory,
        env: _.extend(process.env, {
          PROJECT: project.name
        })
      }));

    if (program.stdout) {
      bash.on('close', process.exit);
    } else {
      var lines = [];

      bash.stdout.pipe(split()).on('data', function (line) {
        lines.push(line);
      });

      // We display things one of three ways--if there was only one line of
      // output we print it on the same line as the project name; if there was
      // more than one line we print it underneath, and if there were no lines
      // of output we print the project name in yellow.
      bash.on('close', function () {
        lines = trimArray(lines);

        if (lines.length > 1) {
          if (program.headers) {
            console.log(chalk.green(project.name));
          }
        } else if (lines.length === 1 && program.headers) {
          process.stdout.write(chalk.green(_.str.rpad(project.name + ':',
            longestName)));
        } else if (!program.ignoreEmptyOutput && program.headers) {
          console.log(chalk.yellow(_.str.rpad(project.name, longestName)));
        }

        if (lines.length) {
          console.log(lines.join('\n'));
        }

        if (lines.length > 1) {
          console.log();
        }
      });
    }
  });

  if (program.warnings) {
    directories.on('missing', function (directory) {
      console.warn(chalk.yellow(directory, 'is missing.'));
    });

    directories.on('file', function (directory) {
      console.warn(chalk.yellow(directory, 'is a file, not a directory.'));
    });
  }

  directories.on('error', function (err) {
    console.error('Error:', err);

    process.exit(1);
  });
});
<|endoftext|>


<commit_before>/** @module liaison/schedule */
define(["requirejs-dplugins/has"], function (has) {
	"use strict";

	has.add("js-setimmediate", typeof setImmediate === "function");
	has.add("dom-mutation-observer",
		typeof MutationObserver !== "undefined"
			&& (/\[\s*native\s+code\s*\]/i.test(MutationObserver) // Avoid polyfill version of MutationObserver
				|| !/^\s*function/.test(MutationObserver)));

	/**
	 * Calls a function at the end of microtask.
	 * @function module:liaison/schedule
	 * @param {Function} callback The function to call at the end of microtask.
	 */

	/* global setImmediate, clearImmediate */
	return has("js-setimmediate") ? function (callback) {
			var h = setImmediate(callback);
			return {
				remove: clearImmediate.bind(undefined, h)
			};
		} : (function () {
			var uniqueId = Math.random() + "",
				callbacks = [],
				pseudoDiv = has("dom-mutation-observer") && document.createElement("div");
			if (has("dom-mutation-observer")) {
				pseudoDiv.id = 0;
				new MutationObserver(function () {
					while (callbacks.length > 0) {
						callbacks.shift()();
					}
				}).observe(pseudoDiv, {attributes: true});
			} else {
				window.addEventListener("message", function (event) {
					if (event.data === uniqueId) {
						while (callbacks.length > 0) {
							callbacks.shift()();
						}
					}
				});
			}
			function remove(callback) {
				for (var index; (index = callbacks.indexOf(callback)) >= 0;) {
					callbacks.splice(index, 1);
				}
			}
			return function (callback) {
				has("dom-mutation-observer") ? ++pseudoDiv.id : window.postMessage(uniqueId, "*");
				callbacks.indexOf(callback) < 0 && callbacks.push(callback);
				return {
					remove: remove.bind(undefined, callback)
				};
			};
		})();
});
<commit_msg>Prefer DOM Mutation Observer over setImmediate().<commit_after>/** @module liaison/schedule */
define(["requirejs-dplugins/has"], function (has) {
	"use strict";

	has.add("js-setimmediate", typeof setImmediate === "function");
	has.add("dom-mutation-observer",
		typeof MutationObserver !== "undefined"
			&& (/\[\s*native\s+code\s*\]/i.test(MutationObserver) // Avoid polyfill version of MutationObserver
				|| !/^\s*function/.test(MutationObserver)));

	/**
	 * Calls a function at the end of microtask.
	 * @function module:liaison/schedule
	 * @param {Function} callback The function to call at the end of microtask.
	 */

	/* global setImmediate, clearImmediate */
	return has("js-setimmediate") && !has("dom-mutation-observer") ? function (callback) {
			var h = setImmediate(callback);
			return {
				remove: clearImmediate.bind(undefined, h)
			};
		} : (function () {
			var uniqueId = Math.random() + "",
				callbacks = [],
				pseudoDiv = has("dom-mutation-observer") && document.createElement("div");
			if (has("dom-mutation-observer")) {
				pseudoDiv.id = 0;
				new MutationObserver(function () {
					while (callbacks.length > 0) {
						callbacks.shift()();
					}
				}).observe(pseudoDiv, {attributes: true});
			} else {
				window.addEventListener("message", function (event) {
					if (event.data === uniqueId) {
						while (callbacks.length > 0) {
							callbacks.shift()();
						}
					}
				});
			}
			function remove(callback) {
				for (var index; (index = callbacks.indexOf(callback)) >= 0;) {
					callbacks.splice(index, 1);
				}
			}
			return function (callback) {
				has("dom-mutation-observer") ? ++pseudoDiv.id : window.postMessage(uniqueId, "*");
				callbacks.indexOf(callback) < 0 && callbacks.push(callback);
				return {
					remove: remove.bind(undefined, callback)
				};
			};
		})();
});
<|endoftext|>


<commit_before>/**
 * @fileoverview viewport - calculates viewport position
 * @version 0.0.5
 *
 * @license MIT, see http://github.com/asvd/viewport
 * @copyright 2015 asvd <heliosframework@gmail.com>
 */

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define(['exports'], factory);
    } else if (typeof exports !== 'undefined') {
        factory(exports);
    } else {
        factory((root.viewport = {}));
    }
}(this, function (exports) {
    var entries = [];  // each entry contains a viewport with sections
    var ctx = 40;      // context to substract from the scroll targets

    // for better compression
    var VIEWPORT = 'viewport';
    var EventListener = 'EventListener';
    var addEventListener = 'add'+EventListener;
    var removeEventListener = 'remove'+EventListener;
    var getBoundingClientRect = 'getBoundingClientRect';

    var top    = 'top';
    var bottom = 'bottom';
    var left   = 'left';
    var right  = 'right';

    var Top    = 'Top';
    var Left   = 'Left';

    var Location = 'Location';
    var Start    = 'Start';
    var End      = 'End';
    var Scroll   = 'Scroll';
    var Target   = 'Target'
    var scroll   = 'scroll';
    var resize   = 'resize';
    var length   = 'length';
    var _window  = window;
    var _document = document;
    var _null = null;
    var _Math = Math;
    var Math_min = _Math.min;
    var Math_max = _Math.max;
    var Math_abs = _Math.abs;

    // updates section dimensions upon resize
    // (to avoid calling expensive getBoundingClientRect()
    // on each scrolling act)
    var updateDimensions = function() {
        var i, j, entry, section, offset, vRect, sRect;
        for (i = 0; i < entries.length; i++) {
            entry = entries[i];
            vRect = entry.r[getBoundingClientRect]();
            offset = {
                top : entry.r.scrollTop,
                left : entry.r.scrollLeft
            };

            entry.r.rect = {
                left   : vRect.left,
                top    : vRect.top,
                right  : vRect.right,
                bottom : vRect.bottom,
                width  : vRect.right  - vRect.left,
                height : vRect.bottom - vRect.top,
                scrollHeight : entry.r.scrollHeight,
                scrollWidth  : entry.r.scrollWidth
            }

            for (j = 0; j < entry.s.length; j++) {
                section = entry.s[j];
                sRect = section[getBoundingClientRect]();
                // section rectangle relatively to the viewport
                section.rect = {
                    left   : sRect.left   - vRect.left + offset.left,
                    top    : sRect.top    - vRect.top  + offset.top,
                    right  : sRect.right  - vRect.left + offset.left,
                    bottom : sRect.bottom - vRect.top  + offset.top,
                    width  : sRect.right  - sRect.left,
                    height : sRect.bottom - sRect.top
                };
            }
        }
    }

    var reset = function() {
        var i=0, j, isBody, hasViewportClass, classes,
            listener, section, viewport, scroller, entry=_null, sections;

        // running through existing entries and removing listeners
        for (;i < entries[length];) {
            listener = entries[i].r.vpl;
            entries[i++].r[removeEventListener](scroll, listener, 0);
            _window[removeEventListener](resize, listener, 0);
        }

        // rebuilding entries
        entries = [];
        sections = _document.getElementsByClassName('section');
        for (i = 0; i < sections[length];) {
            // searching for a parent viewport
            viewport = section = sections[i++];
            while(1) {
                hasViewportClass = j = 0;
                isBody = viewport == _document.body;
                if (!isBody) {
                    classes = viewport.className.split(' ');
                    for (;j < classes[length];) {
                        if (classes[j++] == VIEWPORT) {
                            hasViewportClass = 1;
                            break;
                        }
                    }
                }

                if (isBody || hasViewportClass) {
                    break;
                }

                viewport = viewport.parentNode;
            }

            // searching for exisiting entry for the viewport
            for (j = 0; j < entries[length]; j++) {
                if (entries[j].v == viewport) {
                    entry = entries[j];
                }
            }

            // creating a new entry if not found
            if (!entry) {
                scroller = viewport.scroller||viewport;
                entry = {
                    v : viewport,
                    r : scroller,
                    s : []  // list of all sections
                };

                // listener invoked upon the viewport scroll
                scroller.vpl = (function(entry) {return function() {
                    var scroller = entry.r;
                    var vRect = scroller.rect;

                    var vTop    = vRect[top];
                    var vLeft   = vRect[left];
                    var vBottom = vRect[bottom];
                    var vRight  = vRect[right];

                    var vMiddle = (vBottom + vTop)/2;
                    var vCenter = (vLeft + vRight)/2;

                    // full scorlling amount
                    var maxVert = vRect.scrollHeight - vRect.height;
                    var maxHoriz = vRect.scrollWidth - vRect.width;

                    // viewport scroll ratio, 0..1
                    var rateVert = maxVert ? scroller[scroll+Top] / maxVert : 0;
                    var rateHoriz = maxHoriz ? scroller[scroll+Left] / maxHoriz : 0;

                    // viewport location point moves along with
                    // viewport scroll to always meet the borders
                    var vMiddlePos = vTop + (vBottom-vTop)*rateVert;
                    var vCenterPos = vLeft + (vRight-vLeft)*rateHoriz;

                    var offset = {
                        top : scroller.scrollTop,
                        left : scroller.scrollLeft
                    }

                    // updating the data for each section
                    // (and searching for the closest section)
                    var closest = _null;
                    var minDist = _null;

                    for (var i = 0; i < entry.s[length];) {
                        var section = entry.s[i++];

                        var sRect = section.rect;
                        var sTop = sRect[top] - offset.top;
                        var sLeft = sRect[left] - offset.left;
                        var sBottom = sRect[bottom] - offset.top;
                        var sRight = sRect[right] - offset.left;
                        var sHeight = sBottom - sTop;
                        var sWidth  = sRight - sLeft;

                        var topOffset = vTop - sTop;
                        var leftOffset = vLeft - sLeft;

                        // viewport location related to the section
                        var vLeftLocation = (vCenterPos - sLeft) / sWidth;
                        var vTopLocation =  (vMiddlePos - sTop)  / sHeight;

                        // viewport to section distance, normalized
                        var vVertDist =
                            Math_max(0, Math_abs(vTopLocation - 0.5) - 0.5);
                        var vHorizDist =
                            Math_max(0, Math_abs(vLeftLocation - 0.5) - 0.5);

                        // squared, but we only need to compare
                        var dist = vVertDist*vVertDist + vHorizDist*vHorizDist;

                        var scrollTopToStart = -topOffset - ctx;
                        var scrollTopToMiddle =
                            (sBottom + sTop)/2 - vMiddle;

                        var scrollLeftToStart = -leftOffset - ctx;
                        var scrollLeftToCenter =
                            (sLeft + sRight)/2 - vCenter;

                        // updating section data concerning the viewport
                        section[VIEWPORT+Top+Start] = topOffset / sHeight;
                        section[VIEWPORT+Top+End] = (vBottom - sTop) / sHeight;

                        section[VIEWPORT+Left+Start] = leftOffset / sWidth;
                        section[VIEWPORT+Left+End] = (vRight - sLeft) / sWidth;

                        section[VIEWPORT+Top+Location] = vTopLocation;
                        section[VIEWPORT+Left+Location] = vLeftLocation;

                        section[VIEWPORT+Scroll+Top+Target] =
                            Math_max(
                                0,
                                Math_min(
                                    maxVert,
                                    scroller[scroll+Top] +
                                        Math_min(scrollTopToStart,
                                                 scrollTopToMiddle)
                                )
                            );

                        section[VIEWPORT+Scroll+Left+Target] =
                            Math_max(
                                0,
                                Math_min(
                                    maxHoriz,
                                    scroller[scroll+Left] +
                                        Math_min(scrollLeftToStart,
                                                 scrollLeftToCenter)
                                )
                            );

                        // checking if the section is closer to the viewport
                        if (minDist === _null || minDist > dist) {
                            minDist = dist;
                            closest = section;
                        }
                    }

                    entry.v.currentSection = closest;
                }})(entry);

                scroller[addEventListener](scroll, scroller.vpl, 0);
                _window[addEventListener](resize, scroller.vpl, 0);

                entries.push(entry);
            }

            // adding section to the entry of the viewport
            entry.s.push(section);
        }

        updateDimensions();
        _window[addEventListener](resize, updateDimensions, 0);

        // initially setting-up the properties
        for (i = 0; i < entries[length];) {
            entries[i++].r.vpl();
        }
    }

    if (_document.readyState == "complete") {
        reset();
    } else {
        _window[addEventListener]("load", reset, 0);
    }

    exports.reset = reset;
    exports.updateDimensions = updateDimensions;
}));

<commit_msg>fix viewport scroll position<commit_after>/**
 * @fileoverview viewport - calculates viewport position
 * @version 0.0.5
 *
 * @license MIT, see http://github.com/asvd/viewport
 * @copyright 2015 asvd <heliosframework@gmail.com>
 */

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define(['exports'], factory);
    } else if (typeof exports !== 'undefined') {
        factory(exports);
    } else {
        factory((root.viewport = {}));
    }
}(this, function (exports) {
    var entries = [];  // each entry contains a viewport with sections
    var ctx = 40;      // context to substract from the scroll targets

    // for better compression
    var VIEWPORT = 'viewport';
    var EventListener = 'EventListener';
    var addEventListener = 'add'+EventListener;
    var removeEventListener = 'remove'+EventListener;
    var getBoundingClientRect = 'getBoundingClientRect';

    var top    = 'top';
    var bottom = 'bottom';
    var left   = 'left';
    var right  = 'right';

    var Top    = 'Top';
    var Left   = 'Left';

    var Location = 'Location';
    var Start    = 'Start';
    var End      = 'End';
    var Scroll   = 'Scroll';
    var Target   = 'Target'
    var scroll   = 'scroll';
    var resize   = 'resize';
    var length   = 'length';
    var _window  = window;
    var _document = document;
    var _null = null;
    var _Math = Math;
    var Math_min = _Math.min;
    var Math_max = _Math.max;
    var Math_abs = _Math.abs;

    // updates section dimensions upon resize
    // (to avoid calling expensive getBoundingClientRect()
    // on each scrolling act)
    var updateDimensions = function() {
        var i, j, entry, section, offset, vRect, sRect;
        for (i = 0; i < entries.length; i++) {
            entry = entries[i];
            vRect = entry.r[getBoundingClientRect]();
            offset = {
                top : entry.r.scrollTop,
                left : entry.r.scrollLeft
            };

            entry.r.rect = {
                left   : vRect.left,
                top    : vRect.top,
                right  : vRect.right,
                bottom : vRect.bottom,
                width  : vRect.right  - vRect.left,
                height : vRect.bottom - vRect.top,
                scrollHeight : entry.r.scrollHeight,
                scrollWidth  : entry.r.scrollWidth
            }

            for (j = 0; j < entry.s.length; j++) {
                section = entry.s[j];
                sRect = section[getBoundingClientRect]();
                // section rectangle relatively to the viewport
                section.rect = {
                    left   : sRect.left   - vRect.left + offset.left,
                    top    : sRect.top    - vRect.top  + offset.top,
                    right  : sRect.right  - vRect.left + offset.left,
                    bottom : sRect.bottom - vRect.top  + offset.top,
                    width  : sRect.right  - sRect.left,
                    height : sRect.bottom - sRect.top
                };
            }
        }
    }

    var reset = function() {
        var i=0, j, isBody, hasViewportClass, classes,
            listener, section, viewport, scroller, entry=_null, sections;

        // running through existing entries and removing listeners
        for (;i < entries[length];) {
            listener = entries[i].r.vpl;
            entries[i++].r[removeEventListener](scroll, listener, 0);
            _window[removeEventListener](resize, listener, 0);
        }

        // rebuilding entries
        entries = [];
        sections = _document.getElementsByClassName('section');
        for (i = 0; i < sections[length];) {
            // searching for a parent viewport
            viewport = section = sections[i++];
            while(1) {
                hasViewportClass = j = 0;
                isBody = viewport == _document.body;
                if (!isBody) {
                    classes = viewport.className.split(' ');
                    for (;j < classes[length];) {
                        if (classes[j++] == VIEWPORT) {
                            hasViewportClass = 1;
                            break;
                        }
                    }
                }

                if (isBody || hasViewportClass) {
                    break;
                }

                viewport = viewport.parentNode;
            }

            // searching for exisiting entry for the viewport
            for (j = 0; j < entries[length]; j++) {
                if (entries[j].v == viewport) {
                    entry = entries[j];
                }
            }

            // creating a new entry if not found
            if (!entry) {
                scroller = viewport.scroller||viewport;
                entry = {
                    v : viewport,
                    r : scroller,
                    s : []  // list of all sections
                };

                // listener invoked upon the viewport scroll
                scroller.vpl = (function(entry) {return function() {
                    var scroller = entry.r;
                    var vRect = scroller.rect;

                    var vTop    = vRect[top];
                    var vLeft   = vRect[left];
                    var vBottom = vRect[bottom];
                    var vRight  = vRect[right];

                    var vMiddle = (vBottom + vTop)/2;
                    var vCenter = (vLeft + vRight)/2;

                    // full scorlling amount
                    var maxVert = vRect.scrollHeight - vRect.height;
                    var maxHoriz = vRect.scrollWidth - vRect.width;

                    // viewport scroll ratio, 0..1
                    var rateVert = maxVert ? scroller[scroll+Top] / maxVert : 0;
                    var rateHoriz = maxHoriz ? scroller[scroll+Left] / maxHoriz : 0;

                    // viewport location point moves along with
                    // viewport scroll to always meet the borders
                    var vMiddlePos = vTop + (vBottom-vTop)*rateVert;
                    var vCenterPos = vLeft + (vRight-vLeft)*rateHoriz;

                    var offset = {
                        top : scroller.scrollTop,
                        left : scroller.scrollLeft
                    }

                    // updating the data for each section
                    // (and searching for the closest section)
                    var closest = _null;
                    var minDist = _null;

                    for (var i = 0; i < entry.s[length];) {
                        var section = entry.s[i++];

                        var sRect = section.rect;
                        var sTop = sRect[top] + vRect[top] - offset.top;
                        var sLeft = sRect[left] + vRect[left] - offset.left;
                        var sBottom = sRect[bottom] + vRect[top] - offset.top;
                        var sRight = sRect[right] + vRect[left] - offset.left;
                        var sHeight = sBottom - sTop;
                        var sWidth  = sRight - sLeft;

                        var topOffset = vTop - sTop;
                        var leftOffset = vLeft - sLeft;

                        // viewport location related to the section
                        var vLeftLocation = (vCenterPos - sLeft) / sWidth;
                        var vTopLocation =  (vMiddlePos - sTop)  / sHeight;

                        // viewport to section distance, normalized
                        var vVertDist =
                            Math_max(0, Math_abs(vTopLocation - 0.5) - 0.5);
                        var vHorizDist =
                            Math_max(0, Math_abs(vLeftLocation - 0.5) - 0.5);

                        // squared, but we only need to compare
                        var dist = vVertDist*vVertDist + vHorizDist*vHorizDist;

                        var scrollTopToStart = -topOffset - ctx;
                        var scrollTopToMiddle =
                            (sBottom + sTop)/2 - vMiddle;

                        var scrollLeftToStart = -leftOffset - ctx;
                        var scrollLeftToCenter =
                            (sLeft + sRight)/2 - vCenter;

                        // updating section data concerning the viewport
                        section[VIEWPORT+Top+Start] = topOffset / sHeight;
                        section[VIEWPORT+Top+End] = (vBottom - sTop) / sHeight;

                        section[VIEWPORT+Left+Start] = leftOffset / sWidth;
                        section[VIEWPORT+Left+End] = (vRight - sLeft) / sWidth;

                        section[VIEWPORT+Top+Location] = vTopLocation;
                        section[VIEWPORT+Left+Location] = vLeftLocation;

                        section[VIEWPORT+Scroll+Top+Target] =
                            Math_max(
                                0,
                                Math_min(
                                    maxVert,
                                    scroller[scroll+Top] +
                                        Math_min(scrollTopToStart,
                                                 scrollTopToMiddle)
                                )
                            );

                        section[VIEWPORT+Scroll+Left+Target] =
                            Math_max(
                                0,
                                Math_min(
                                    maxHoriz,
                                    scroller[scroll+Left] +
                                        Math_min(scrollLeftToStart,
                                                 scrollLeftToCenter)
                                )
                            );

                        // checking if the section is closer to the viewport
                        if (minDist === _null || minDist > dist) {
                            minDist = dist;
                            closest = section;
                        }
                    }

                    entry.v.currentSection = closest;
                }})(entry);

                scroller[addEventListener](scroll, scroller.vpl, 0);
                _window[addEventListener](resize, scroller.vpl, 0);

                entries.push(entry);
            }

            // adding section to the entry of the viewport
            entry.s.push(section);
        }

        updateDimensions();
        _window[addEventListener](resize, updateDimensions, 0);

        // initially setting-up the properties
        for (i = 0; i < entries[length];) {
            entries[i++].r.vpl();
        }
    }

    if (_document.readyState == "complete") {
        reset();
    } else {
        _window[addEventListener]("load", reset, 0);
    }

    exports.reset = reset;
    exports.updateDimensions = updateDimensions;
}));

<|endoftext|>


<commit_before>UI(UI.dom).get('isElement');
UI.dom.element = function(obj){
  if(typeof obj === 'string'){
    var obj = {
      type:obj,
      $:document.createElement(obj),
    };
  }else if(UI.dom.isElement(obj)){
    obj = {
      $:obj,
    };
  }else{
    obj.$ = document.createElement(obj.type);
  }
  if(obj.parent){
    UI.dom.element.prototype.appendTo.call(obj,obj.parent);
  }
  return obj;
};
UI.dom.element.prototype.appendTo = function(parent){
  this.parent = parent.$ ? parent : UI.dom(parent);
  this.parent.$.appendChild(this.$);
};
UI.dom.element.prototype.__proto__ = UI.dom.prototype;
<commit_msg>Update element.js<commit_after>UI(UI.dom).get('isElement');
UI.dom.element = function(obj){
  if(typeof obj === 'string'){
    var obj = {
      type:obj,
      $:document.createElement(obj),
    };
  }else if(UI.dom.isElement(obj)){
    obj = {
      $:obj,
    };
  }else{
    obj.$ = document.createElement(obj.type);
  }
  if(obj.parent){
    UI.dom.element.prototype.appendTo.call(obj,obj.parent);
  }
  return obj;
};
UI.dom.element.prototype.appendTo = function(parent){
  console.log(this);
  console.log(parent);
  this.parent = parent.$ ? parent : UI.dom.element(parent);
  this.parent.$.appendChild(this.$);
  console.log(this.parent);
  return this;
};
UI.dom.element.prototype.__proto__ = UI.dom.prototype;
<|endoftext|>


<commit_before>const path = require('path');
const glob = require('glob');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const devMode = process.env.NODE_ENV !== 'production'

module.exports = (env, options) => ({
  optimization: {
    minimizer: [
      new TerserPlugin({ cache: true, parallel: true, sourceMap: devMode }),
      new OptimizeCSSAssetsPlugin({})
    ]
  },
  entry: {
    'app': glob.sync('./vendor/**/*.js').concat(['./js/app.js'])
  },
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, '../priv/static/js'),
    publicPath: '/js/'
  },
  devtool: devMode ? 'source-map' : undefined,
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      },
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {
              sourceMap: devMode
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({ filename: '../css/app.css' }),
    new CopyWebpackPlugin([{ from: 'static/', to: '../' }])
  ]
});
<commit_msg>Fix devMode in webpack.config.js (#3725)<commit_after>const path = require('path');
const glob = require('glob');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = (env, options) => {
  const devMode = options.mode !== 'production';

  return {
    optimization: {
      minimizer: [
        new TerserPlugin({ cache: true, parallel: true, sourceMap: devMode }),
        new OptimizeCSSAssetsPlugin({})
      ]
    },
    entry: {
      'app': glob.sync('./vendor/**/*.js').concat(['./js/app.js'])
    },
    output: {
      filename: '[name].js',
      path: path.resolve(__dirname, '../priv/static/js'),
      publicPath: '/js/'
    },
    devtool: devMode ? 'source-map' : undefined,
    module: {
      rules: [
        {
          test: /\.js$/,
          exclude: /node_modules/,
          use: {
            loader: 'babel-loader'
          }
        },
        {
          test: /\.css$/,
          use: [
            MiniCssExtractPlugin.loader,
            {
              loader: 'css-loader',
              options: {
                sourceMap: devMode
              }
            }
          ]
        }
      ]
    },
    plugins: [
      new MiniCssExtractPlugin({ filename: '../css/app.css' }),
      new CopyWebpackPlugin([{ from: 'static/', to: '../' }])
    ]
  }
};
<|endoftext|>


<commit_before>import Ember from 'ember';
import BaseAuthenticator from './base';

const { RSVP, isEmpty } = Ember;

/**
  Authenticator that wraps the
  [Torii library](https://github.com/Vestorly/torii) and thus allows to connect
  any external authentication provider that torii defines a provider for.

  In order to use this authenticator, __the application needs to have the
  [torii addon](https://github.com/Vestorly/torii) installed and must inject
  the torii service into the authenticator__:

  ```js
  // app/authenticators/torii.js
  import ToriiAuthenticator from 'ember-simple-auth/authenticators/torii';

  export default ToriiAuthenticator.extend(
    torii: Ember.inject.service()
  )
  ```

  @class ToriiAuthenticator
  @module ember-simple-auth/authenticators/torii
  @extends BaseAuthenticator
  @public
*/
export default BaseAuthenticator.extend({
  _provider: null,

  /**
    Restores the session by calling the torii provider's `fetch` method.

    __Many torii providers do not implement the `fetch` method__. If the
    provider in use does not implement the method simply add it as follows:

    ```js
    // app/providers/facebook.js
    import FacebookOauth2Provider from 'torii/providers/facebook-oauth2';

    export default FacebookOauth2Provider.extend({
      fetch(data) {
        return data;
      }
    });
    ```

    @method restore
    @param {Object} data The data to restore the session from
    @return {Ember.RSVP.Promise} A promise that when it resolves results in the session becoming or remaining authenticated
    @public
  */
  restore(data) {
    this._assertToriiIsPresent();

    data = data || {};
    return new RSVP.Promise((resolve, reject) => {
      if (!isEmpty(data.provider)) {
        let { provider } = data;
        this.get('torii').fetch(data.provider, data).then((data) => {
          this._resolveWith(provider, data, resolve);
        }, () => {
          delete this._provider;
          reject();
        });
      } else {
        delete this._provider;
        reject();
      }
    });
  },

  /**
    Authenticates the session by opening the specified torii provider. For more
    documentation on torii and its providers abstraction, see the
    [project's README](https://github.com/Vestorly/torii#readme), specifically
    the
    [section on providers](https://github.com/Vestorly/torii#configuring-a-torii-provider).

    @method authenticate
    @param {String} provider The torii provider to authenticate the session with
    @param {Object} options The options to pass to the torii provider
    @return {Ember.RSVP.Promise} A promise that when it resolves results in the session becoming authenticated
    @public
  */
  authenticate(provider, options) {
    this._assertToriiIsPresent();

    return new RSVP.Promise((resolve, reject) => {
      this.get('torii').open(provider, options || {}).then((data) => {
        this._resolveWith(provider, data, resolve);
      }, reject);
    });
  },

  /**
    Closes the torii provider. If the provider is successfully closed, this
    method returns a resolving promise, otherwise it will return a rejecting
    promise, thus intercepting session invalidation.

    @method invalidate
    @return {Ember.RSVP.Promise} A promise that when it resolves results in the session being invalidated
    @public
  */
  invalidate(data) {
    this._assertToriiIsPresent();

    data = data || {};
    return new RSVP.Promise((resolve, reject) => {
      if (!isEmpty(data.provider)) {
        let { provider } = data;
        this.get('torii').close(data.provider, data).then((data) => {
          data = data || {};
          this._resolveWith(provider, data, resolve);
        }, () => {
          delete this._provider;
          reject();
        });
      } else {
        delete this._provider;
        reject();
      }
    });
  },

  _resolveWith(provider, data, resolve) {
    data.provider = provider;
    this._provider = data.provider;
    resolve(data);
  },

  _assertToriiIsPresent() {
    const torii = this.get('torii');
    Ember.assert('You are trying to use the torii authenticator but torii is not available. Inject torii into the authenticator with "torii: Ember.inject.service()".', Ember.isPresent(torii));
  }
});
<commit_msg>Removing the code to process a response from the torii close method.<commit_after>import Ember from 'ember';
import BaseAuthenticator from './base';

const { RSVP, isEmpty } = Ember;

/**
  Authenticator that wraps the
  [Torii library](https://github.com/Vestorly/torii) and thus allows to connect
  any external authentication provider that torii defines a provider for.

  In order to use this authenticator, __the application needs to have the
  [torii addon](https://github.com/Vestorly/torii) installed and must inject
  the torii service into the authenticator__:

  ```js
  // app/authenticators/torii.js
  import ToriiAuthenticator from 'ember-simple-auth/authenticators/torii';

  export default ToriiAuthenticator.extend(
    torii: Ember.inject.service()
  )
  ```

  @class ToriiAuthenticator
  @module ember-simple-auth/authenticators/torii
  @extends BaseAuthenticator
  @public
*/
export default BaseAuthenticator.extend({
  _provider: null,

  /**
    Restores the session by calling the torii provider's `fetch` method.

    __Many torii providers do not implement the `fetch` method__. If the
    provider in use does not implement the method simply add it as follows:

    ```js
    // app/providers/facebook.js
    import FacebookOauth2Provider from 'torii/providers/facebook-oauth2';

    export default FacebookOauth2Provider.extend({
      fetch(data) {
        return data;
      }
    });
    ```

    @method restore
    @param {Object} data The data to restore the session from
    @return {Ember.RSVP.Promise} A promise that when it resolves results in the session becoming or remaining authenticated
    @public
  */
  restore(data) {
    this._assertToriiIsPresent();

    data = data || {};
    return new RSVP.Promise((resolve, reject) => {
      if (!isEmpty(data.provider)) {
        let { provider } = data;
        this.get('torii').fetch(data.provider, data).then((data) => {
          this._resolveWith(provider, data, resolve);
        }, () => {
          delete this._provider;
          reject();
        });
      } else {
        delete this._provider;
        reject();
      }
    });
  },

  /**
    Authenticates the session by opening the specified torii provider. For more
    documentation on torii and its providers abstraction, see the
    [project's README](https://github.com/Vestorly/torii#readme), specifically
    the
    [section on providers](https://github.com/Vestorly/torii#configuring-a-torii-provider).

    @method authenticate
    @param {String} provider The torii provider to authenticate the session with
    @param {Object} options The options to pass to the torii provider
    @return {Ember.RSVP.Promise} A promise that when it resolves results in the session becoming authenticated
    @public
  */
  authenticate(provider, options) {
    this._assertToriiIsPresent();

    return new RSVP.Promise((resolve, reject) => {
      this.get('torii').open(provider, options || {}).then((data) => {
        this._resolveWith(provider, data, resolve);
      }, reject);
    });
  },

  /**
    Closes the torii provider. If the provider is successfully closed, this
    method returns a resolving promise, otherwise it will return a rejecting
    promise, thus intercepting session invalidation.

    @method invalidate
    @return {Ember.RSVP.Promise} A promise that when it resolves results in the session being invalidated
    @public
  */
  invalidate(data) {
    return new RSVP.Promise((resolve, reject) => {
      this.get('torii').close(this._provider, data).then(() => {
        delete this._provider;
        resolve();
      }, reject);
    });
  },

  _resolveWith(provider, data, resolve) {
    data.provider = provider;
    this._provider = data.provider;
    resolve(data);
  },

  _assertToriiIsPresent() {
    const torii = this.get('torii');
    Ember.assert('You are trying to use the torii authenticator but torii is not available. Inject torii into the authenticator with "torii: Ember.inject.service()".', Ember.isPresent(torii));
  }
});
<|endoftext|>


<commit_before>define(function (require) {
  require("jquery");
  var Utils = require("core/Utils");
  var Storage = require("core/Storage");
  var Inherits = require("core/Inherits");
  var Dialog = require("core/Dialog");
  var Class = require("core/Class");
  var Grid = require("core/Control/Grid");
  var Field = require("core/Control/Field/Field");

  var TEMPLATE = '' +
'' +
'
' +
'  ' +
'

' +
'
';

  var ITEM_TEMPLATE = '' +
'
' +
'  ' +
'  ' +
'
';

  function create_search(self, root, field) {
    self._search.on("click", function(event) {
      var dialog = new Dialog();
      var grid = new Grid();
      var select_panel = "";
      dialog.init(function(panel_id) {
        var dfd = new $.Deferred;

        var selector = "#" + panel_id;
        var panel = $(selector);
        panel.addClass("selector");

        grid.init(selector, Grid.create_columns(self._class))
        .then(function() {
          grid.multi_search(true);
          grid.multi_select(field.datatype.properties.multi_selectable);
          grid.select_column(true);
          grid.toolbar(true);
          var data = Object.keys(self._objects).map(function(id) { return self._objects[id]; });
          grid.data(data);
          grid.refresh();
          dfd.resolve();
        });
        return dfd.promise();
      });
      dialog.title("Select");
      dialog.buttons([
        {
          text : "OK",
          click: function (event) {
            var recids = grid.selection();
            console.log("[OK] clicked. selection=" + recids);
            self._value = recids;
            self.refresh();
            dialog.close();
          }
        },
        {
          text : "Cancel",
          click: function (event) {
            console.log("[Cancel] clicked.");
            dialog.close();
          }
        }
      ]);
      dialog.size(300, 400);

      dialog.open();
    });
  }

  function Selector() {
    Field.call(this, "core/Control/Field", "Selector");
    this._search = null;
    this._description = null;
    this._list = null;
    this._class = null;
    this._objects = null;
    this._fixed = null;
    this._value = null;
  }
  Inherits(Selector, Field);

  Selector.prototype.init = function(selector, field) {
    var dfd = new $.Deferred;
    // Set member fields
    var root = $(selector);
    if (0 < root.children()) {
      dfd.resolve();
      return dfd.promise();
    }

    // Create form tags
    root.empty();
    root.append(TEMPLATE);
    // Label
    var label = root.children("label");
    label.text(field.label);
    // Seach Icon
    this._search = root.find("div > i[name='search']");
    // Description
    this._description = root.find("div > span[name='description']");
    this._description.text(field.datatype.properties.description);
    // List
    this._list = root.find("div > div[name='list']");
    this._list.on("click", "i[name=remove]", function(event) {
      var i = $(event.originalEvent.target);
      var record = i.parent();
      record.remove();
      var id = record.attr("id");
      self._value = self._value.filter(function (_id) { return _id != id; });
    });
    // Mouse over/out on icons.
    root.on("mouseover", "i", function(event) {
      var i = $(event.originalEvent.target);
      i.css("cursor", "pointer");
    });
    root.on("mouseout", "i", function(event) {
      var i = $(event.originalEvent.target);
      i.css("cursor", "auto");
    });

    var self = this;
    var class_id = field.datatype.properties.class_id;
    console.assert(!(!class_id), field);
    $.when(
      Utils.load_css("/core/Control/Field/Selector.css"),
      Storage.read(Class.CLASS_ID, class_id).done(function(data) { self._class = data; }),
      Storage.read(class_id).done(function(data) { self._objects = data; })
    ).then(function() {
      create_search(self, root, field);
      dfd.resolve();
    });
    return dfd.promise();
  };

  Selector.prototype.edit = function(on) {
    var self = this;
    if (on) {
      this._search.show();
      this._list.find("i[name=remove]").show();
    } else {
      this._search.hide();
      this._list.find("i[name=remove]").hide();
    }
  };

  Selector.prototype.backuped = function() {
    return this._fixed;
  };

  Selector.prototype.commit = function() {
    this._fixed = this._value;
  };

  Selector.prototype.restore = function() {
    this._value = this._fixed;
    this.refresh();
  };

  Selector.prototype.data = function(value) {
    if (arguments.length == 0) {
      return this._value;
    } else {
      this._value = value;
      this._fixed = value;
      this.refresh();
    }
  };

  Selector.prototype.update = function(keys) {

  };

  Selector.prototype.refresh = function() {
    console.log("Selector.refresh called.");
    this._list.empty();

    if (!this._value) {
      this._value = [];
    }
    var self = this;
    var objects = this._value.map(function(id) { return self._objects[id]; });
    var captions = (new Class(this._class)).captions(objects);
    for (var i = 0; i < captions.length; i++) {
      var file = this._value[i];
      this._list.append(ITEM_TEMPLATE);
      var record = this._list.find("div.item:last-child");
      record.attr("id", this._value[i]);
      record.find("span").text(captions[i]);
    }
  };

  return Selector;
});
<commit_msg>Fixed Selector.js bug (Even if in editting mode, remove icon was shown.)<commit_after>define(function (require) {
  require("jquery");
  var Utils = require("core/Utils");
  var Storage = require("core/Storage");
  var Inherits = require("core/Inherits");
  var Dialog = require("core/Dialog");
  var Class = require("core/Class");
  var Grid = require("core/Control/Grid");
  var Field = require("core/Control/Field/Field");

  var TEMPLATE = '' +
'' +
'
' +
'  ' +
'

' +
'
';

  var ITEM_TEMPLATE = '' +
'
' +
'  ' +
'  ' +
'
';

  function create_search(self, root, field) {
    self._search.on("click", function(event) {
      var dialog = new Dialog();
      var grid = new Grid();
      var select_panel = "";
      dialog.init(function(panel_id) {
        var dfd = new $.Deferred;

        var selector = "#" + panel_id;
        var panel = $(selector);
        panel.addClass("selector");

        grid.init(selector, Grid.create_columns(self._class))
        .then(function() {
          grid.multi_search(true);
          grid.multi_select(field.datatype.properties.multi_selectable);
          grid.select_column(true);
          grid.toolbar(true);
          var data = Object.keys(self._objects).map(function(id) { return self._objects[id]; });
          grid.data(data);
          grid.refresh();
          dfd.resolve();
        });
        return dfd.promise();
      });
      dialog.title("Select");
      dialog.buttons([
        {
          text : "OK",
          click: function (event) {
            var recids = grid.selection();
            console.log("[OK] clicked. selection=" + recids);
            self._value = recids;
            self.refresh();
            dialog.close();
          }
        },
        {
          text : "Cancel",
          click: function (event) {
            console.log("[Cancel] clicked.");
            dialog.close();
          }
        }
      ]);
      dialog.size(300, 400);

      dialog.open();
    });
  }

  function Selector() {
    Field.call(this, "core/Control/Field", "Selector");
    this._search = null;
    this._description = null;
    this._list = null;
    this._class = null;
    this._objects = null;
    this._fixed = null;
    this._value = null;
    this._editting = false;
  }
  Inherits(Selector, Field);

  Selector.prototype.init = function(selector, field) {
    var dfd = new $.Deferred;
    // Set member fields
    var root = $(selector);
    if (0 < root.children()) {
      dfd.resolve();
      return dfd.promise();
    }

    // Create form tags
    root.empty();
    root.append(TEMPLATE);
    // Label
    var label = root.children("label");
    label.text(field.label);
    // Seach Icon
    this._search = root.find("div > i[name='search']");
    // Description
    this._description = root.find("div > span[name='description']");
    this._description.text(field.datatype.properties.description);
    // List
    this._list = root.find("div > div[name='list']");
    this._list.on("click", "div.item > i", function(event) {
      var i = $(event.originalEvent.target);
      var record = i.parent();
      record.remove();
      var id = record.attr("id");
      self._value = self._value.filter(function (_id) { return _id != id; });
    });
    // Mouse over/out on icons.
    root.on("mouseover", "i", function(event) {
      var i = $(event.originalEvent.target);
      i.css("cursor", "pointer");
    });
    root.on("mouseout", "i", function(event) {
      var i = $(event.originalEvent.target);
      i.css("cursor", "auto");
    });

    var self = this;
    var class_id = field.datatype.properties.class_id;
    console.assert(!(!class_id), field);
    $.when(
      Utils.load_css("/core/Control/Field/Selector.css"),
      Storage.read(Class.CLASS_ID, class_id).done(function(data) { self._class = data; }),
      Storage.read(class_id).done(function(data) { self._objects = data; })
    ).then(function() {
      create_search(self, root, field);
      self.edit(false);
      dfd.resolve();
    });
    return dfd.promise();
  };

  Selector.prototype.edit = function(on) {
    this._editting = on;
    if (on) {
      this._search.show();
      this._list.find("div.item > i").css("display", "inline");
    } else {
      this._search.hide();
      this._list.find("div.item > i").css("display", "none")
    }
  };

  Selector.prototype.backuped = function() {
    return this._fixed;
  };

  Selector.prototype.commit = function() {
    this._fixed = this._value;
  };

  Selector.prototype.restore = function() {
    this._value = this._fixed;
    this.refresh();
  };

  Selector.prototype.data = function(value) {
    if (arguments.length == 0) {
      return this._value;
    } else {
      this._value = value;
      this._fixed = value;
      this.refresh();
    }
  };

  Selector.prototype.update = function(keys) {

  };

  Selector.prototype.refresh = function() {
    console.log("Selector.refresh called.");
    this._list.empty();

    if (!this._value) {
      this._value = [];
    }
    var self = this;
    var objects = this._value.map(function(id) { return self._objects[id]; });
    var captions = (new Class(this._class)).captions(objects);
    for (var i = 0; i < captions.length; i++) {
      var file = this._value[i];
      this._list.append(ITEM_TEMPLATE);
      var record = this._list.find("div.item:last-child");
      record.attr("id", this._value[i]);
      record.find("span").text(captions[i]);
    }
    this.edit(this._editting);
  };

  return Selector;
});
<|endoftext|>


<commit_before>/*
	Class: UI.Button
		Creates button and let you _initEvents events action

	Extend:
		<UI.Control>

	Arguments:
		options

	Options:
		text - (string) Text to show in button
		submit - (boolean) Set to true if you want your button act as a submit button

	Example:
	(start code)
		var button = new UI.Button({
			text        : 'i am a new UI.Button',
			onClick     : { alert('click') }
		}).inject(document.body);
	(end)

	Implied global:
		UI,
		Class,Event

*/

UI.Button = new Class({

	Extends: UI.Control,

	name: 'button',

	options: {
		type: null, // push, file
		element: {
			tag: 'span'
		}
	},

	/*
	Function: _initElement
		private function

		Create a textLabel and call parent method

	Returns:
		(void)

	See also:
		<UI.Control::_initElement>
		<UI.Component::_initElement>
	*/

	_initElement: function(){
		this.parent();
		var opts = this.options;
			type = opts.type;

		if (type === null)
			type = 'icon-text';

		//console.log(type, type.indexOf('icon'));

		if (opts.text && type != 'icon')
			this.element.set('html', opts.text);
		//var text = opts.type.match(/text/g);

		this.element.set('title', opts.text);

		if ((opts.icon && type.indexOf('icon') > -1) || type == 'file')
			this._initIcon();

		this._initClass();

		if (this.options.clss)
			this.element.addClass(this.options.clss);

		if (opts.type == 'file') {
			this._initFile();
		}
	},

	_initIcon: function() {
		var opts = this.options;

		var tag = 'span';
		if (type == 'file')	tag = 'label';

		var pos = 'top';
		if (type == 'text-icon')
			pos = 'bottom';

		this.icon = new Element(tag, {
			'class': 'button-icon',
			for: 'upload'
		}).inject(this.element, pos);

		this.icon.addClass(opts.icon);
	},

	_initFile: function() {
		var self = this;

		var file = new Element('input', {
			type: 'file',
			name: 'upload',
			id: 'upload'
		}).inject(this.element);

		file.addEvent('change', function(info) {
			//console.log('change', info);
		});

		file.onchange = function(info) {
			var files = this.files;
			self.fireEvent('upload', files);

			//console.log(fileList);
		};

		this.addEvent('injected', function() {
			var coord = self.icon.getCoordinates();

			coord.top = '0';
			coord.left = '0';

			file.setStyles(coord);
		});
	},

	_initEvents: function(){
		this.parent();

		var self = this,
			opts = this.options,
			state = opts.state;

		this.element.addEvents({
			mousedown: function(e) {
				self.fireEvent('mousedown');
				e.stop();
			},
			click: function(e){
				e.stopPropagation();
				if (opts.emit && self.state != 'disabled')
					self.fireEvent(opts.emit);
					self.fireEvent('press', opts.emit);

				if (opts.call && self.state != 'disabled')
					opts.call();
			},
			mouseup: function(){
				if (opts.type == 'check') {
					if (self.state == 'checked')
						self.setState(null);
					else self.setState('checked');
				}

			}
		});
	},

	/*
		function : _initClass

			Build the split containers

	*/
	_initClass: function() {
		var opts = this.options;
		//console.log(this.name);

		if (this.options.klss)
			this.element.addClass(this.options.klss);

		if (this.options.type)
			this.element.addClass('type-' + this.options.type);

		this.element.addClass(opts.prefix + this.name);
	}
});

<commit_msg>Make Upload button work for Document App<commit_after>/*
	Class: UI.Button
		Creates button and let you _initEvents events action

	Extend:
		<UI.Control>

	Arguments:
		options

	Options:
		text - (string) Text to show in button
		submit - (boolean) Set to true if you want your button act as a submit button

	Example:
	(start code)
		var button = new UI.Button({
			text        : 'i am a new UI.Button',
			onClick     : { alert('click') }
		}).inject(document.body);
	(end)

	Implied global:
		UI,
		Class,Event

*/

UI.Button = new Class({

	Extends: UI.Control,

	name: 'button',

	options: {
		type: null, // push, file
		element: {
			tag: 'span'
		}
	},

	/*
	Function: _initElement
		private function

		Create a textLabel and call parent method

	Returns:
		(void)

	See also:
		<UI.Control::_initElement>
		<UI.Component::_initElement>
	*/

	_initElement: function(){
		this.parent();
		var opts = this.options;
			type = opts.type;

		if (type === null)
			type = 'icon-text';

		//console.log(type, type.indexOf('icon'));

		if (opts.text && type != 'icon')
			this.element.set('html', opts.text);
		//var text = opts.type.match(/text/g);

		this.element.set('title', opts.text);

		if ((opts.icon && type.indexOf('icon') > -1) || type == 'file')
			this._initIcon();

		this._initClass();

		if (this.options.clss)
			this.element.addClass(this.options.clss);

		if (opts.type == 'file') {
			this._initFile();
		}
	},

	_initIcon: function() {
		var opts = this.options;

		var tag = 'span';
		if (type == 'file')	tag = 'label';

		var pos = 'top';
		if (type == 'text-icon')
			pos = 'bottom';

		this.icon = new Element(tag, {
			'class': 'button-icon',
			for: 'upload'
		}).inject(this.element, pos);

		this.icon.addClass(opts.icon);
	},

	_initFile: function() {
		var self = this;

		var file = new Element('input', {
			type: 'file',
			name: 'upload',
			id: 'upload'
		}).inject(this.element);

		file.addEvent('change', function(info) {
			//console.log('change', info);
		});

		file.onchange = function(info) {
			var files = this.files;
			console.log(files);
			if (files)
			self.fireEvent('uploadFile', [files]);

		};

		this.addEvent('injected', function() {
			var coord = self.icon.getCoordinates();

			coord.top = '0';
			coord.left = '0';

			file.setStyles(coord);
		});
	},

	_initEvents: function(){
		this.parent();

		var self = this,
			opts = this.options,
			state = opts.state;

		this.element.addEvents({
			mousedown: function(e) {
				self.fireEvent('mousedown');
				e.stop();
			},
			click: function(e){
				e.stopPropagation();
				if (opts.emit && self.state != 'disabled')
					self.fireEvent(opts.emit);
					self.fireEvent('press', opts.emit);

				if (opts.call && self.state != 'disabled')
					opts.call();
			},
			mouseup: function(){
				if (opts.type == 'check') {
					if (self.state == 'checked')
						self.setState(null);
					else self.setState('checked');
				}

			}
		});
	},

	/*
		function : _initClass

			Build the split containers

	*/
	_initClass: function() {
		var opts = this.options;
		//console.log(this.name);

		if (this.options.klss)
			this.element.addClass(this.options.klss);

		if (this.options.type)
			this.element.addClass('type-' + this.options.type);

		this.element.addClass(opts.prefix + this.name);
	}
});

<|endoftext|>