<commit_before>var iconFeature = new ol.Feature({
  geometry: new ol.geom.Point(ol.proj.transform([12.5469185, 41.8286509], 'EPSG:4326', 'EPSG:3857')),
  name: 'Null Island',
  population: 4000,
  rainfall: 500
});

var iconStyle = new ol.style.Style({
  image: new ol.style.Icon(({
    anchor: [0.5, 46],
    anchorXUnits: 'fraction',
    anchorYUnits: 'pixels',
    opacity: 0.75,
    src: 'data/icon.png'
  }))
});

iconFeature.setStyle(iconStyle);

// var vectorSource = new ol.source.Vector({
//   features: [iconFeature]
// });

function centerMap(center) {
  map.getView().setCenter(ol.proj.transform(center, 'EPSG:4326', 'EPSG:3857'));
}

// function takes features array
function plotMarkers(featuresArray) {
  // first remove old ones
  var oldFeatures = vectorSource.getFeatures();
  function removeMarker(m) {
    vectorSource.removeFeature(m);
  }
  oldFeatures.forEach(removeMarker);

  // then add new ones
  vectorSource.addFeatures(featuresArray);
}

var vectorSource = new ol.source.GeoJSON(
    /** @type {olx.source.GeoJSONOptions} */ ({
      object: {
        "type": "FeatureCollection",
        "features": [{
          "type": "Feature",
          "geometry": {
            "type": "Point",
            "coordinates": [12.5464756318, 41.829304, 130]
          },
          "id": 162,
          "properties": {
            "pointcloud": "data/sites/162/cloud_las.js",
            "description": "Pyramid",
            "thumbnail": "data/sites/162/P1120067.JPG",
            "site_context": "Funerary",
            "site_interpretation": "Funerary tower",
            "condition": "Damaged"
          },
          "bbox": [12.546372, 41.829228, 121.484, 12.546579, 41.829381, 144.177]
        }, {
          "type": "Feature",
          "geometry": {
            "type": "Point",
            "coordinates": [12.546488, 41.828926, 120.21]
          },
          "id": 13,
          "properties": {
            "pointcloud": "data/sites/13/cloud_las.js",
            "description": "Block",
            "thumbnail": "data/sites/13/IMG_0040.JPG",
            "site_context": "Unknown",
            "site_interpretation": "Unknown",
            "condition": "Chipped"
          },
          "bbox":[12.546479, 41.828919, 120, 12.546497, 41.828934, 120.42]
        }],
        "crs": {
          "type":"name",
          "properties": {
              "name": "urn:ogc:def:crs:OGC:1.3:CRS84"
              // "name": "EPSG:3857"
          }
        }
      },
    projection: 'EPSG:3857'
    }));

var vectorLayer = new ol.layer.Vector({
  source: vectorSource
});

var mapType1 = new ol.source.MapQuest({layer: 'sat'});
var mapType2 = new ol.source.TileWMS({
    url: 'http://maps.opengeo.org/geowebcache/service/wms',
    params: {LAYERS: 'openstreetmap', VERSION: '1.1.1'}
  });
var mapType3 = new ol.source.TileWMS({
    url: 'http://maps.opengeo.org/geowebcache/service/wms',
    params: {LAYERS: 'bluemarble', VERSION: '1.1.1'}
  });
var mapType4 = new ol.source.MapQuest({layer: 'osm'});

var rasterLayer = new ol.layer.Tile({
  source: mapType4
});

var map = new ol.Map({
  layers: [rasterLayer, vectorLayer],
  // layers: [vectorLayer, rasterLayer], // Note: order makes a difference, last one is on top
  // layers: [rasterLayer],
  target: document.getElementById('overhead-map'),
  view: new ol.View({
    center: ol.proj.transform([12.5469185, 41.8286509], 'EPSG:4326', 'EPSG:3857'),
    zoom: 10
  })
});

/*
var element = document.getElementById('popup');

var popup = new ol.Overlay({
  element: element,
  positioning: 'bottom-center',
  stopEvent: false
});
map.addOverlay(popup);

// display popup on click
map.on('click', function(evt) {
  var feature = map.forEachFeatureAtPixel(evt.pixel,
      function(feature, layer) {
        return feature;
      });
  if (feature) {
    var geometry = feature.getGeometry();
    var coord = geometry.getCoordinates();
    popup.setPosition(coord);
    $(element).popover({
      'placement': 'top',
      'html': true,
      'content': feature.get('name')
    });
    $(element).popover('show');
  } else {
    $(element).popover('destroy');
  }
});

// change mouse cursor when over marker
$(map.getViewport()).on('mousemove', function(e) {
  var pixel = map.getEventPixel(e.originalEvent);
  var hit = map.forEachFeatureAtPixel(pixel, function(feature, layer) {
    return true;
  });
  if (hit) {
    map.getTarget().style.cursor = 'pointer';
  } else {
    map.getTarget().style.cursor = '';
  }
});
*/<commit_msg>Cleanup code<commit_after>function centerMap(center) {
  map.getView().setCenter(ol.proj.transform(center, 'EPSG:4326', 'EPSG:3857'));
}

// function takes features array
function plotMarkers(featuresArray) {
  // first remove old ones
  var oldFeatures = vectorSource.getFeatures();
  function removeMarker(m) {
    vectorSource.removeFeature(m);
  }
  oldFeatures.forEach(removeMarker);

  // then add new ones
  vectorSource.addFeatures(featuresArray);
}

var vectorSource = new ol.source.GeoJSON(
    /** @type {olx.source.GeoJSONOptions} */ ({
      object: {
        "type": "FeatureCollection",
        "features": [{
          "type": "Feature",
          "geometry": {
            "type": "Point",
            "coordinates": [12.5464756318, 41.829304, 130]
          },
          "id": 162,
          "properties": {
            "pointcloud": "data/sites/162/cloud_las.js",
            "description": "Pyramid",
            "thumbnail": "data/sites/162/P1120067.JPG",
            "site_context": "Funerary",
            "site_interpretation": "Funerary tower",
            "condition": "Damaged"
          },
          "bbox": [12.546372, 41.829228, 121.484, 12.546579, 41.829381, 144.177]
        }, {
          "type": "Feature",
          "geometry": {
            "type": "Point",
            "coordinates": [12.546488, 41.828926, 120.21]
          },
          "id": 13,
          "properties": {
            "pointcloud": "data/sites/13/cloud_las.js",
            "description": "Block",
            "thumbnail": "data/sites/13/IMG_0040.JPG",
            "site_context": "Unknown",
            "site_interpretation": "Unknown",
            "condition": "Chipped"
          },
          "bbox":[12.546479, 41.828919, 120, 12.546497, 41.828934, 120.42]
        }],
        "crs": {
          "type":"name",
          "properties": {
              "name": "urn:ogc:def:crs:OGC:1.3:CRS84"
              // "name": "EPSG:3857"
          }
        }
      },
    projection: 'EPSG:3857'
    }));

var vectorLayer = new ol.layer.Vector({
  source: vectorSource
});

var mapType1 = new ol.source.MapQuest({layer: 'sat'});
var mapType2 = new ol.source.TileWMS({
    url: 'http://maps.opengeo.org/geowebcache/service/wms',
    params: {LAYERS: 'openstreetmap', VERSION: '1.1.1'}
  });
var mapType3 = new ol.source.TileWMS({
    url: 'http://maps.opengeo.org/geowebcache/service/wms',
    params: {LAYERS: 'bluemarble', VERSION: '1.1.1'}
  });
var mapType4 = new ol.source.MapQuest({layer: 'osm'});

var rasterLayer = new ol.layer.Tile({
  source: mapType4
});

var map = new ol.Map({
  layers: [rasterLayer, vectorLayer],
  target: document.getElementById('overhead-map'),
  view: new ol.View({
    center: ol.proj.transform([12.5469185, 41.8286509], 'EPSG:4326', 'EPSG:3857'),
    zoom: 10
  })
});
<|endoftext|>


<commit_before>import jwt from 'jsonwebtoken';
import fetch from 'node-fetch';

function getGitHubUserDetails(accessToken) {
  return fetch(`https://api.github.com/user?access_token=${accessToken}`)
    .then(res => {
      if (res.status === 200) {
        return res;
      }
      throw new Error(res.statusText);
    })
    .then(res => res.json())
    .then(json => ({ authenticationProvider: 'github', authenticationId: json.id }));
}

function generateCSBToken(authenticationDetails) {
  return jwt.sign(authenticationDetails, process.env.CSBLOGS_JWT_SECRET);
}

export function generateAuthenticationToken(authenticationProvider, accessToken) { // eslint-disable-line import/prefer-default-export
  let getUserDetailsPromise = null;
  switch (authenticationProvider.toLowerCase()) {
    case 'github':
      getUserDetailsPromise = getGitHubUserDetails;
      break;
    default:
      throw new Error('Authentication Provider Required');
  }

  return getUserDetailsPromise(accessToken).then(generateCSBToken);
}
<commit_msg>Force id to string<commit_after>import jwt from 'jsonwebtoken';
import fetch from 'node-fetch';

function getGitHubUserDetails(accessToken) {
  return fetch(`https://api.github.com/user?access_token=${accessToken}`)
    .then(res => {
      if (res.status === 200) {
        return res;
      }
      throw new Error(res.statusText);
    })
    .then(res => res.json())
    .then(json => ({ authenticationProvider: 'github', authenticationId: `${json.id}` }));
}

function generateCSBToken(authenticationDetails) {
  return jwt.sign(authenticationDetails, process.env.CSBLOGS_JWT_SECRET);
}

export function generateAuthenticationToken(authenticationProvider, accessToken) { // eslint-disable-line import/prefer-default-export
  let getUserDetailsPromise = null;
  switch (authenticationProvider.toLowerCase()) {
    case 'github':
      getUserDetailsPromise = getGitHubUserDetails;
      break;
    default:
      throw new Error('Authentication Provider Required');
  }

  return getUserDetailsPromise(accessToken).then(generateCSBToken);
}
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import classNames from 'classnames'

import { YMaps} from 'react-yandex-maps';
import { Map } from 'react-yandex-maps';
import { Placemark } from 'react-yandex-maps';

import page from '../Page'
import styles from './Contacts.module.css'

class Contacts extends Component {
  state = {

  }

  render() {

    return (

Места продаж

              <svg width="96" height="96" viewBox="0 0 96 96" fill="none" xmlns="http://www.w3.org/2000/svg">
                <g clip-path="url(#clip0)">
                <path d="M48 8.64845C60.8174 8.64845 62.3341 8.69799 67.3966 8.92854C72.0762 9.14194 74.618 9.92314 76.3099 10.5805C78.5507 11.4512 80.1493 12.4916 81.8298 14.1702C83.5103 15.8507 84.5507 17.4493 85.4195 19.69C86.0769 21.382 86.8581 23.9238 87.0715 28.6033C87.302 33.664 87.3515 35.1826 87.3515 48C87.3515 60.8174 87.302 62.334 87.0715 67.3966C86.8581 72.0762 86.0769 74.6179 85.4195 76.3099C84.5488 78.5506 83.5084 80.1492 81.8298 81.8297C80.1493 83.5103 78.5507 84.5506 76.3099 85.4194C74.618 86.0768 72.0762 86.858 67.3966 87.0714C62.336 87.302 60.8174 87.3515 48 87.3515C35.1826 87.3515 33.664 87.302 28.6034 87.0714C23.9238 86.858 21.382 86.0768 19.6901 85.4194C17.4494 84.5487 15.8507 83.5084 14.1702 81.8297C12.4897 80.1492 11.4493 78.5506 10.5805 76.3099C9.92315 74.6179 9.14195 72.0762 8.92855 67.3966C8.698 62.3359 8.64846 60.8174 8.64846 48C8.64846 35.1826 8.698 33.6659 8.92855 28.6033C9.14195 23.9238 9.92315 21.382 10.5805 19.69C11.4513 17.4493 12.4916 15.8507 14.1702 14.1702C15.8507 12.4897 17.4494 11.4493 19.6901 10.5805C21.382 9.92314 23.9238 9.14194 28.6034 8.92854C33.6659 8.69799 35.1826 8.64845 48 8.64845ZM48 0C34.9635 0 33.3287 0.0552556 28.209 0.289616C23.1007 0.52207 19.6119 1.33376 16.5576 2.5208C13.4004 3.74785 10.7234 5.38837 8.05589 8.05779C5.38838 10.7253 3.74595 13.4023 2.5208 16.5576C1.33376 19.6119 0.522071 23.1007 0.289616 28.2089C0.0552556 33.3287 0 34.9635 0 48C0 61.0365 0.0552556 62.6713 0.289616 67.791C0.522071 72.8993 1.33376 76.388 2.5208 79.4423C3.74786 82.5995 5.38838 85.2766 8.0578 87.9441C10.7272 90.6135 13.4024 92.254 16.5595 93.4811C19.6119 94.6681 23.1026 95.4798 28.2109 95.7122C33.3306 95.9466 34.9654 96.0019 48.0019 96.0019C61.0384 96.0019 62.6732 95.9466 67.793 95.7122C72.9012 95.4798 76.3919 94.6681 79.4443 93.4811C82.6015 92.254 85.2785 90.6135 87.946 87.9441C90.6154 85.2746 92.256 82.5995 93.483 79.4423C94.6701 76.3899 95.4818 72.8993 95.7142 67.791C95.9486 62.6713 96.0038 61.0365 96.0038 48C96.0038 34.9635 95.9486 33.3287 95.7142 28.2089C95.4818 23.1007 94.6701 19.61 93.483 16.5576C92.256 13.4004 90.6154 10.7234 87.946 8.05589C85.2766 5.38647 82.6015 3.74595 79.4443 2.51889C76.3881 1.33376 72.8993 0.52207 67.7911 0.289616C62.6713 0.0552556 61.0365 0 48 0Z" fill="#FAFAFA"/>
                <path d="M48 23.3522C34.3862 23.3522 23.3522 34.3881 23.3522 48C23.3522 61.6119 34.3881 72.6478 48 72.6478C61.6119 72.6478 72.6478 61.6119 72.6478 48C72.6478 34.3881 61.6138 23.3522 48 23.3522ZM48 63.9994C39.1629 63.9994 32.0006 56.8352 32.0006 48C32.0006 39.1629 39.1648 32.0006 48 32.0006C56.8352 32.0006 63.9994 39.1648 63.9994 48C63.9994 56.8371 56.8371 63.9994 48 63.9994Z" fill="#FAFAFA"/>
                <path d="M73.6233 28.1365C76.8044 28.1365 79.3833 25.5577 79.3833 22.3766C79.3833 19.1955 76.8044 16.6167 73.6233 16.6167C70.4422 16.6167 67.8634 19.1955 67.8634 22.3766C67.8634 25.5577 70.4422 28.1365 73.6233 28.1365Z" fill="#FAFAFA"/>
                </g>
                <defs>
                <clipPath id="clip0">
                <rect width="96" height="96" fill="white"/>
                </clipPath>
                </defs>
              </svg>

            Golovina.brand

{this.props.mail}

Москва

                3-я улица Ямского поля, 9к5

                Телефон: +7 910 134-07-77

Ежедневно с 12:00 до 20:00

                <YMaps>

                    <Map width={'100%'} defaultState={{ center: [55.7826, 37.5804], zoom: 16, width: 100 }}>
                      <Placemark defaultGeometry={[55.7826, 37.5804]} />
                    </Map>

                </YMaps>

Нижний Новгород

                Ошарская, 61

                Телефон: +7 910 134-07-77

Ежедневно с 12:00 до 20:00

                <YMaps>

                    <Map width={'100%'} defaultState={{ center: [56.3112, 44.0157], zoom: 16, width: '600px'  }}>
                      <Placemark defaultGeometry={[56.3112, 44.0157]} />
                    </Map>

                </YMaps>

    )
  }
}

export default Contacts
<commit_msg>Смена графика и телефонов на странице контактов<commit_after>import React, { Component } from 'react'
import classNames from 'classnames'

import { YMaps} from 'react-yandex-maps';
import { Map } from 'react-yandex-maps';
import { Placemark } from 'react-yandex-maps';

import page from '../Page'
import styles from './Contacts.module.css'

class Contacts extends Component {
  state = {

  }

  render() {

    return (

Места продаж

              <svg width="96" height="96" viewBox="0 0 96 96" fill="none" xmlns="http://www.w3.org/2000/svg">
                <g clip-path="url(#clip0)">
                <path d="M48 8.64845C60.8174 8.64845 62.3341 8.69799 67.3966 8.92854C72.0762 9.14194 74.618 9.92314 76.3099 10.5805C78.5507 11.4512 80.1493 12.4916 81.8298 14.1702C83.5103 15.8507 84.5507 17.4493 85.4195 19.69C86.0769 21.382 86.8581 23.9238 87.0715 28.6033C87.302 33.664 87.3515 35.1826 87.3515 48C87.3515 60.8174 87.302 62.334 87.0715 67.3966C86.8581 72.0762 86.0769 74.6179 85.4195 76.3099C84.5488 78.5506 83.5084 80.1492 81.8298 81.8297C80.1493 83.5103 78.5507 84.5506 76.3099 85.4194C74.618 86.0768 72.0762 86.858 67.3966 87.0714C62.336 87.302 60.8174 87.3515 48 87.3515C35.1826 87.3515 33.664 87.302 28.6034 87.0714C23.9238 86.858 21.382 86.0768 19.6901 85.4194C17.4494 84.5487 15.8507 83.5084 14.1702 81.8297C12.4897 80.1492 11.4493 78.5506 10.5805 76.3099C9.92315 74.6179 9.14195 72.0762 8.92855 67.3966C8.698 62.3359 8.64846 60.8174 8.64846 48C8.64846 35.1826 8.698 33.6659 8.92855 28.6033C9.14195 23.9238 9.92315 21.382 10.5805 19.69C11.4513 17.4493 12.4916 15.8507 14.1702 14.1702C15.8507 12.4897 17.4494 11.4493 19.6901 10.5805C21.382 9.92314 23.9238 9.14194 28.6034 8.92854C33.6659 8.69799 35.1826 8.64845 48 8.64845ZM48 0C34.9635 0 33.3287 0.0552556 28.209 0.289616C23.1007 0.52207 19.6119 1.33376 16.5576 2.5208C13.4004 3.74785 10.7234 5.38837 8.05589 8.05779C5.38838 10.7253 3.74595 13.4023 2.5208 16.5576C1.33376 19.6119 0.522071 23.1007 0.289616 28.2089C0.0552556 33.3287 0 34.9635 0 48C0 61.0365 0.0552556 62.6713 0.289616 67.791C0.522071 72.8993 1.33376 76.388 2.5208 79.4423C3.74786 82.5995 5.38838 85.2766 8.0578 87.9441C10.7272 90.6135 13.4024 92.254 16.5595 93.4811C19.6119 94.6681 23.1026 95.4798 28.2109 95.7122C33.3306 95.9466 34.9654 96.0019 48.0019 96.0019C61.0384 96.0019 62.6732 95.9466 67.793 95.7122C72.9012 95.4798 76.3919 94.6681 79.4443 93.4811C82.6015 92.254 85.2785 90.6135 87.946 87.9441C90.6154 85.2746 92.256 82.5995 93.483 79.4423C94.6701 76.3899 95.4818 72.8993 95.7142 67.791C95.9486 62.6713 96.0038 61.0365 96.0038 48C96.0038 34.9635 95.9486 33.3287 95.7142 28.2089C95.4818 23.1007 94.6701 19.61 93.483 16.5576C92.256 13.4004 90.6154 10.7234 87.946 8.05589C85.2766 5.38647 82.6015 3.74595 79.4443 2.51889C76.3881 1.33376 72.8993 0.52207 67.7911 0.289616C62.6713 0.0552556 61.0365 0 48 0Z" fill="#FAFAFA"/>
                <path d="M48 23.3522C34.3862 23.3522 23.3522 34.3881 23.3522 48C23.3522 61.6119 34.3881 72.6478 48 72.6478C61.6119 72.6478 72.6478 61.6119 72.6478 48C72.6478 34.3881 61.6138 23.3522 48 23.3522ZM48 63.9994C39.1629 63.9994 32.0006 56.8352 32.0006 48C32.0006 39.1629 39.1648 32.0006 48 32.0006C56.8352 32.0006 63.9994 39.1648 63.9994 48C63.9994 56.8371 56.8371 63.9994 48 63.9994Z" fill="#FAFAFA"/>
                <path d="M73.6233 28.1365C76.8044 28.1365 79.3833 25.5577 79.3833 22.3766C79.3833 19.1955 76.8044 16.6167 73.6233 16.6167C70.4422 16.6167 67.8634 19.1955 67.8634 22.3766C67.8634 25.5577 70.4422 28.1365 73.6233 28.1365Z" fill="#FAFAFA"/>
                </g>
                <defs>
                <clipPath id="clip0">
                <rect width="96" height="96" fill="white"/>
                </clipPath>
                </defs>
              </svg>

            Golovina.brand

{this.props.mail}

Москва

                3-я улица Ямского поля, 9к5

                Телефон: +7 985 800-07-48, +7 985 714-55-58

Ежедневно с 13:00 до 21:00

                <YMaps>

                    <Map width={'100%'} defaultState={{ center: [55.7826, 37.5804], zoom: 16, width: 100 }}>
                      <Placemark defaultGeometry={[55.7826, 37.5804]} />
                    </Map>

                </YMaps>

Нижний Новгород

                Ошарская, 61

                Телефон: +7 910 134-07-77

Ежедневно с 12:00 до 20:00

                <YMaps>

                    <Map width={'100%'} defaultState={{ center: [56.3112, 44.0157], zoom: 16, width: '600px'  }}>
                      <Placemark defaultGeometry={[56.3112, 44.0157]} />
                    </Map>

                </YMaps>

    )
  }
}

export default Contacts
<|endoftext|>


<commit_before>import { always, equals, T } from '../rambda.js'
import { cond } from './cond'

test('returns a function', () => {
  expect(typeof cond([])).toEqual('function')
})

test('returns a conditional function', () => {
  const fn = cond([
    [ equals(0), always('water freezes at 0°C') ],
    [ equals(100), always('water boils at 100°C') ],
    [
      T,
      function(temp){
        return 'nothing special happens at ' + temp + '°C'
      },
    ],
  ])
  expect(fn(0)).toEqual('water freezes at 0°C')
  expect(fn(50)).toEqual('nothing special happens at 50°C')
  expect(fn(100)).toEqual('water boils at 100°C')
})

test('returns a function which returns undefined if none of the predicates matches', () => {
  const fn = cond([
    [ equals('foo'), always(1) ],
    [ equals('bar'), always(2) ],
  ])
  expect(fn('quux')).toEqual(undefined)
})

test('predicates are tested in order', () => {
  const fn = cond([
    [ T, always('foo') ],
    [ T, always('bar') ],
    [ T, always('baz') ],
  ])
  expect(fn()).toEqual('foo')
})

test('forwards all arguments to predicates and to transformers', () => {
  const fn = cond([
    [
      function(_, x){
        return x === 42
      },
      () => arguments.length,
    ],
  ])
  expect(fn(
    21, 42, 84
  )).toEqual(3)
})

test('retains highest predicate arity', () => {
  const fn = cond([
    [ nAry(2, T), T ],
    [ nAry(3, T), T ],
    [ nAry(1, T), T ],
  ])
  expect(fn.length).toEqual(3)
})
<commit_msg>fix@issue #373 r.cond<commit_after>import { always, equals, T } from '../rambda.js'
import { cond } from './cond'

test('returns a function', () => {
  expect(typeof cond([])).toEqual('function')
})

test('returns a conditional function', () => {
  const fn = cond([
    [ equals(0), always('water freezes at 0°C') ],
    [ equals(100), always('water boils at 100°C') ],
    [
      T,
      function(temp){
        return 'nothing special happens at ' + temp + '°C'
      },
    ],
  ])
  expect(fn(0)).toEqual('water freezes at 0°C')
  expect(fn(50)).toEqual('nothing special happens at 50°C')
  expect(fn(100)).toEqual('water boils at 100°C')
})

test('returns a function which returns undefined if none of the predicates matches', () => {
  const fn = cond([
    [ equals('foo'), always(1) ],
    [ equals('bar'), always(2) ],
  ])
  expect(fn('quux')).toEqual(undefined)
})

test('predicates are tested in order', () => {
  const fn = cond([
    [ T, always('foo') ],
    [ T, always('bar') ],
    [ T, always('baz') ],
  ])
  expect(fn()).toEqual('foo')
})
<|endoftext|>


<commit_before>app.modules = {
  'vanilla': {
    'Reference': {
      'page': 'Creating a page',
      'navigator': 'Stack navigation',
      'tabbar': 'Using tabs',
      'splitter': 'Side menu',
      'list': 'Lists',
      'lazy-repeat': 'Infinite lists',
      'pull-hook': 'Pull to refresh',
      'carousel': 'Carousel',
      'dialog': 'Dialogs',
      'popover': 'Popover',
      'input': 'Form input',
      'switch': 'Switches',
      'button': 'Buttons',
      'range': 'Range sliders',
      'icon': 'Icons',
      'if': 'Conditional element',
      'progress': 'Progress',
      'fab': 'Floating action button',
      'speed-dial': 'Speed dial',
      'ripple': 'Ripple effect'
    }
  },
  'angular1': {
    'Getting started': {
      'Introduction': 'Introduction',
      'Data binding': 'Data binding',
      'Event handling': 'Event handling'
    },
    'Reference': {
      'page': 'Creating a page',
      'navigator': 'Stack navigation',
      'tabbar': 'Using tabs',
      'splitter': 'Side menu',
      'list': 'Lists',
      'lazy-repeat': 'Infinite lists',
      'pull-hook': 'Pull to refresh',
      'carousel': 'Carousel',
      'dialog': 'Dialogs',
      'popover': 'Popover',
      'input': 'Form input',
      'switch': 'Switches',
      'button': 'Buttons',
      'range': 'Range sliders',
      'icon': 'Icons',
      'if': 'Conditional element',
      'progress': 'Progress',
      'fab': 'Floating action button',
      'speed-dial': 'Speed dial',
      'ripple': 'Ripple effect'
    }
  },
  'angular2': {

  },
  'react': {
    'Getting started': {
      'Using the components': 'Using the components'
    },
    'Reference': {
      'button': 'Button',
      'carousel': 'Carousel',
      'dialog': 'Dialogs',
      'fab': 'Floating action button',
      'icon': 'Icons',
      'input': 'Form input',
      'lazy-list': 'Infinite scrolling',
      'list': 'Lists',
      'navigator': 'Stack navigation',
      'page': 'Page'
/*      'popover': 'Popover',
      'progress': 'Progress indicators',
      'pull-hook': 'Pull to refresh',
      'ripple': 'Ripple effect',
      'speed-dial': 'Speed dial',
      'splitter': 'Splitter',
      'tabbar': 'Tabs',
      'toolbar': 'Toolbar'*/
    }
  }
};

<commit_msg>Remove comment<commit_after>app.modules = {
  'vanilla': {
    'Reference': {
      'page': 'Creating a page',
      'navigator': 'Stack navigation',
      'tabbar': 'Using tabs',
      'splitter': 'Side menu',
      'list': 'Lists',
      'lazy-repeat': 'Infinite lists',
      'pull-hook': 'Pull to refresh',
      'carousel': 'Carousel',
      'dialog': 'Dialogs',
      'popover': 'Popover',
      'input': 'Form input',
      'switch': 'Switches',
      'button': 'Buttons',
      'range': 'Range sliders',
      'icon': 'Icons',
      'if': 'Conditional element',
      'progress': 'Progress',
      'fab': 'Floating action button',
      'speed-dial': 'Speed dial',
      'ripple': 'Ripple effect'
    }
  },
  'angular1': {
    'Getting started': {
      'Introduction': 'Introduction',
      'Data binding': 'Data binding',
      'Event handling': 'Event handling'
    },
    'Reference': {
      'page': 'Creating a page',
      'navigator': 'Stack navigation',
      'tabbar': 'Using tabs',
      'splitter': 'Side menu',
      'list': 'Lists',
      'lazy-repeat': 'Infinite lists',
      'pull-hook': 'Pull to refresh',
      'carousel': 'Carousel',
      'dialog': 'Dialogs',
      'popover': 'Popover',
      'input': 'Form input',
      'switch': 'Switches',
      'button': 'Buttons',
      'range': 'Range sliders',
      'icon': 'Icons',
      'if': 'Conditional element',
      'progress': 'Progress',
      'fab': 'Floating action button',
      'speed-dial': 'Speed dial',
      'ripple': 'Ripple effect'
    }
  },
  'angular2': {

  },
  'react': {
    'Getting started': {
      'Using the components': 'Using the components'
    },
    'Reference': {
      'button': 'Button',
      'carousel': 'Carousel',
      'dialog': 'Dialogs',
      'fab': 'Floating action button',
      'icon': 'Icons',
      'input': 'Form input',
      'lazy-list': 'Infinite scrolling',
      'list': 'Lists',
      'navigator': 'Stack navigation',
      'page': 'Page'
      'popover': 'Popover',
      'progress': 'Progress indicators',
      'pull-hook': 'Pull to refresh',
      'ripple': 'Ripple effect',
      'speed-dial': 'Speed dial',
      'splitter': 'Splitter',
      'tabbar': 'Tabs',
      'toolbar': 'Toolbar'
    }
  }
};

<|endoftext|>


<commit_before>import { SETTING_CHANGE } from '../actions/settings';
import { COLUMN_ADD, COLUMN_REMOVE, COLUMN_MOVE } from '../actions/columns';
import { STORE_HYDRATE } from '../actions/store';
import { Map as ImmutableMap, fromJS } from 'immutable';
import uuid from '../uuid';

const initialState = ImmutableMap({
  onboarded: false,

  home: ImmutableMap({
    shows: ImmutableMap({
      reblog: true,
      reply: true,
    }),

    regex: ImmutableMap({
      body: '',
    }),
  }),

  notifications: ImmutableMap({
    alerts: ImmutableMap({
      follow: true,
      favourite: true,
      reblog: true,
      mention: true,
    }),

    shows: ImmutableMap({
      follow: true,
      favourite: true,
      reblog: true,
      mention: true,
    }),

    sounds: ImmutableMap({
      follow: true,
      favourite: true,
      reblog: true,
      mention: true,
    }),
  }),

  community: ImmutableMap({
    regex: ImmutableMap({
      body: '',
    }),
  }),

  public: ImmutableMap({
    regex: ImmutableMap({
      body: '',
    }),
  }),

  area: Immutable.Map({
    regex: Immutable.Map({
      body: '',
    }),

    area: Immutable.Map({
      body: 'kansai',
    }),
  }),
});

const defaultColumns = fromJS([
  { id: 'COMPOSE', uuid: uuid(), params: {} },
  { id: 'HOME', uuid: uuid(), params: {} },
  { id: 'NOTIFICATIONS', uuid: uuid(), params: {} },
]);

const hydrate = (state, settings) => state.mergeDeep(settings).update('columns', (val = defaultColumns) => val);

const moveColumn = (state, uuid, direction) => {
  const columns  = state.get('columns');
  const index    = columns.findIndex(item => item.get('uuid') === uuid);
  const newIndex = index + direction;

  let newColumns;

  newColumns = columns.splice(index, 1);
  newColumns = newColumns.splice(newIndex, 0, columns.get(index));

  return state.set('columns', newColumns);
};

export default function settings(state = initialState, action) {
  switch(action.type) {
  case STORE_HYDRATE:
    return hydrate(state, action.state.get('settings'));
  case SETTING_CHANGE:
    return state.setIn(action.key, action.value);
  case COLUMN_ADD:
    return state.update('columns', list => list.push(fromJS({ id: action.id, uuid: uuid(), params: action.params })));
  case COLUMN_REMOVE:
    return state.update('columns', list => list.filterNot(item => item.get('uuid') === action.uuid));
  case COLUMN_MOVE:
    return moveColumn(state, action.uuid, action.direction);
  default:
    return state;
  }
};
<commit_msg>1.5.0アップデートに伴う変更に対応 ImmutableMap<commit_after>import { SETTING_CHANGE } from '../actions/settings';
import { COLUMN_ADD, COLUMN_REMOVE, COLUMN_MOVE } from '../actions/columns';
import { STORE_HYDRATE } from '../actions/store';
import { Map as ImmutableMap, fromJS } from 'immutable';
import uuid from '../uuid';

const initialState = ImmutableMap({
  onboarded: false,

  home: ImmutableMap({
    shows: ImmutableMap({
      reblog: true,
      reply: true,
    }),

    regex: ImmutableMap({
      body: '',
    }),
  }),

  notifications: ImmutableMap({
    alerts: ImmutableMap({
      follow: true,
      favourite: true,
      reblog: true,
      mention: true,
    }),

    shows: ImmutableMap({
      follow: true,
      favourite: true,
      reblog: true,
      mention: true,
    }),

    sounds: ImmutableMap({
      follow: true,
      favourite: true,
      reblog: true,
      mention: true,
    }),
  }),

  community: ImmutableMap({
    regex: ImmutableMap({
      body: '',
    }),
  }),

  public: ImmutableMap({
    regex: ImmutableMap({
      body: '',
    }),
  }),

  area: ImmutableMap({
    regex: ImmutableMap({
      body: '',
    }),

    area: ImmutableMap({
      body: 'kansai',
    }),
  }),
});

const defaultColumns = fromJS([
  { id: 'COMPOSE', uuid: uuid(), params: {} },
  { id: 'HOME', uuid: uuid(), params: {} },
  { id: 'NOTIFICATIONS', uuid: uuid(), params: {} },
]);

const hydrate = (state, settings) => state.mergeDeep(settings).update('columns', (val = defaultColumns) => val);

const moveColumn = (state, uuid, direction) => {
  const columns  = state.get('columns');
  const index    = columns.findIndex(item => item.get('uuid') === uuid);
  const newIndex = index + direction;

  let newColumns;

  newColumns = columns.splice(index, 1);
  newColumns = newColumns.splice(newIndex, 0, columns.get(index));

  return state.set('columns', newColumns);
};

export default function settings(state = initialState, action) {
  switch(action.type) {
  case STORE_HYDRATE:
    return hydrate(state, action.state.get('settings'));
  case SETTING_CHANGE:
    return state.setIn(action.key, action.value);
  case COLUMN_ADD:
    return state.update('columns', list => list.push(fromJS({ id: action.id, uuid: uuid(), params: action.params })));
  case COLUMN_REMOVE:
    return state.update('columns', list => list.filterNot(item => item.get('uuid') === action.uuid));
  case COLUMN_MOVE:
    return moveColumn(state, action.uuid, action.direction);
  default:
    return state;
  }
};
<|endoftext|>


<commit_before>import React, { PropTypes } from 'react'
import {OPTIONS_TAB, FILES_PREVIEW_TAB} from '../../redux/modules/upload'
import UploadModal from './UploadModal'
import UploadPanel from './UploadPanel'
import UploadTabs from './UploadTabs'

export default class UploadContainer extends React.Component {
  static propTypes = {
    state: PropTypes.object.isRequired,
    onFinish: PropTypes.func.isRequired,
    isModal: PropTypes.bool.isRequired,
    actions: PropTypes.object.isRequired
  };

  onClose() {
    this.props.state.upload.get('fileIds').forEach(id => {
      this.props.actions.destroyPlayer(id);
    });
    this.props.actions.cancelUpload();
  }

  onSelectTab(key) {
    this.props.actions.chooseTab(key);
  }

  nextTab() {
    let uploadState = this.props.state.upload.toJS();
    if (uploadState.view.activeTab === FILES_PREVIEW_TAB) {
      this.onSelectTab(OPTIONS_TAB);
    }
    if (uploadState.view.activeTab === OPTIONS_TAB) {
      let options = uploadState.options;
      let settings = this.props.state.settings;
      let groups = options.groups.map(groupId => settings.groups.groups[groupId].name);
      let predictions = options.predictions.map(id => settings.items.predictions.items[id].modelId);
      uploadState.fileIds.forEach(fileId => {
        let file = uploadState.files[fileId].file;
        this.props.actions.postFile(this.props.state.auth.token, fileId, file, {groups, predictions});
      });
      this.props.onFinish();
    }
  }

  getTabs() {
    let state = this.props.state;
    return (
      <UploadTabs token={state.auth.token}
                  uploadState={state.upload.toJS()}
                  playerState={state.media.player.toJS()}
                  settingsState={state.settings}
                  onSelectTab={this.onSelectTab.bind(this)}
                  actions={this.props.actions}
      />
    )
  }

  render () {
    let state = this.props.state;
    let uploadState = state.upload.toJS();

    var isOptionsTab = uploadState.view.activeTab === OPTIONS_TAB;
    var isFilePreviewTab = uploadState.view.activeTab === FILES_PREVIEW_TAB;
    let nextButtonText = (isOptionsTab) ? 'Finish' : 'Next';

    return (

        {
          this.props.isModal &&
          <UploadModal showForm={uploadState.view.showForm}
                       nextTab={this.nextTab.bind(this)}
                       nextButtonText={nextButtonText}
                       onClose={this.onClose.bind(this)}
                       onSelectTab={this.onSelectTab.bind(this)}
          >
            { this.getTabs() }
          </UploadModal>
        }
        {
          !this.props.isModal &&

              {isFilePreviewTab &&
Step 1 of 2: Select files for upload
}
              {isOptionsTab &&
Step 2 of 2: Choose processing options
}

            <UploadPanel showForm={uploadState.view.showForm}
                         nextTab={this.nextTab.bind(this)}
                         nextButtonText={nextButtonText}
                         onClose={this.onClose.bind(this)}
                         onSelectTab={this.onSelectTab.bind(this)}
            >
              { this.getTabs() }
            </UploadPanel>

        }

    )
  }
}
<commit_msg>fix upload file with groups<commit_after>import React, { PropTypes } from 'react'
import {OPTIONS_TAB, FILES_PREVIEW_TAB} from '../../redux/modules/upload'
import UploadModal from './UploadModal'
import UploadPanel from './UploadPanel'
import UploadTabs from './UploadTabs'

export default class UploadContainer extends React.Component {
  static propTypes = {
    state: PropTypes.object.isRequired,
    onFinish: PropTypes.func.isRequired,
    isModal: PropTypes.bool.isRequired,
    actions: PropTypes.object.isRequired
  };

  onClose() {
    this.props.state.upload.get('fileIds').forEach(id => {
      this.props.actions.destroyPlayer(id);
    });
    this.props.actions.cancelUpload();
  }

  onSelectTab(key) {
    this.props.actions.chooseTab(key);
  }

  nextTab() {
    let uploadState = this.props.state.upload.toJS();
    if (uploadState.view.activeTab === FILES_PREVIEW_TAB) {
      this.onSelectTab(OPTIONS_TAB);
    }
    if (uploadState.view.activeTab === OPTIONS_TAB) {
      let options = uploadState.options;
      let settings = this.props.state.settings;
      let groups = options.groups.map(groupId => settings.groups.getIn(['groups', groupId, 'name']));
      let predictions = options.predictions.map(id => settings.items(['predictions', 'items', id, 'modelId']));
      uploadState.fileIds.forEach(fileId => {
        let file = uploadState.files[fileId].file;
        this.props.actions.postFile(this.props.state.auth.token, fileId, file, {groups, predictions});
      });
      this.props.onFinish();
    }
  }

  getTabs() {
    let state = this.props.state;
    return (
      <UploadTabs token={state.auth.token}
                  uploadState={state.upload.toJS()}
                  playerState={state.media.player.toJS()}
                  settingsState={state.settings}
                  onSelectTab={this.onSelectTab.bind(this)}
                  actions={this.props.actions}
      />
    )
  }

  render () {
    let state = this.props.state;
    let uploadState = state.upload.toJS();

    var isOptionsTab = uploadState.view.activeTab === OPTIONS_TAB;
    var isFilePreviewTab = uploadState.view.activeTab === FILES_PREVIEW_TAB;
    let nextButtonText = (isOptionsTab) ? 'Finish' : 'Next';

    return (

        {
          this.props.isModal &&
          <UploadModal showForm={uploadState.view.showForm}
                       nextTab={this.nextTab.bind(this)}
                       nextButtonText={nextButtonText}
                       onClose={this.onClose.bind(this)}
                       onSelectTab={this.onSelectTab.bind(this)}
          >
            { this.getTabs() }
          </UploadModal>
        }
        {
          !this.props.isModal &&

              {isFilePreviewTab &&
Step 1 of 2: Select files for upload
}
              {isOptionsTab &&
Step 2 of 2: Choose processing options
}

            <UploadPanel showForm={uploadState.view.showForm}
                         nextTab={this.nextTab.bind(this)}
                         nextButtonText={nextButtonText}
                         onClose={this.onClose.bind(this)}
                         onSelectTab={this.onSelectTab.bind(this)}
            >
              { this.getTabs() }
            </UploadPanel>

        }

    )
  }
}
<|endoftext|>


<commit_before>'use strict';

angular.module('ddsApp').directive('montantRessource', function(SituationService) {
    function getOnGoingQuestion (individu, ressource, currentMonth) {
        var subject = {
            'demandeur': 'Vous',
            'conjoint': 'Votre conjoint',
            'enfant': individu.firstName
        }[individu.role],
            verbPrefix = ressource.id == 'pensionsAlimentairesVersees' ? 'verser' : 'percevr',
            verbSufix = individu.role == 'demandeur' ? 'ez' : 'a',
            ressourceLabel = ressource.interuptionQuestionLabel || ressource.prefix + ' ' + ressource.label.slice(0,1).toLowerCase() + ressource.label.slice(1);

        return [subject, verbPrefix + verbSufix, ressourceLabel, 'en', currentMonth].join(' ') + '.';
    }

    return {
        restrict: 'E',
        require: 'ngModel',
        replace: true,
        templateUrl: 'partials/foyer/capture-montant-ressource.html',
        scope: {
            individu: '=',
            ressourceType: '=',
            dateDeValeur: '=',
            index: '=',
            form: '=',
        },
        link: function(scope, element, attrs, ngModel) {
            var momentDebutAnnee = moment(scope.dateDeValeur).subtract('years', 1);
            scope.debutAnneeGlissante = momentDebutAnnee.format('MMMM YYYY');
            scope.months = SituationService.getMonths(scope.dateDeValeur);
            scope.currentMonth = moment(scope.dateDeValeur).format('MMMM YYYY');
            scope.isNumber = angular.isNumber;
            scope.onGoingLabel = getOnGoingQuestion(scope.individu, scope.ressourceType, scope.currentMonth);

            function checkSumConsistency() {
                scope.monthsSum = scope.ressource.montantsMensuels.reduce(function(sum, current) {
                    return sum + current;
                }, 0);

                ngModel.$setValidity('valuesConsistency', scope.ressource.montantAnnuel >= scope.monthsSum);
            }

            scope.$watch('ressource.montantsMensuels', checkSumConsistency, true);
            scope.$watch('ressource.montantAnnuel', checkSumConsistency);

            scope.shouldAskDateArretDeTravail = function() {
                return ['indJourMaladie', 'indJourMaladieProf', 'indJourAccidentDuTravail'].indexOf(scope.ressourceType.id) >= 0;
            };

            ngModel.$render = function() {
                scope.ressource = ngModel.$viewValue;
            };
        }
    };
});
<commit_msg>Don't ask date arret if no IJSS first month<commit_after>'use strict';

angular.module('ddsApp').directive('montantRessource', function(SituationService) {
    function getOnGoingQuestion (individu, ressource, currentMonth) {
        var subject = {
            'demandeur': 'Vous',
            'conjoint': 'Votre conjoint',
            'enfant': individu.firstName
        }[individu.role],
            verbPrefix = ressource.id == 'pensionsAlimentairesVersees' ? 'verser' : 'percevr',
            verbSufix = individu.role == 'demandeur' ? 'ez' : 'a',
            ressourceLabel = ressource.interuptionQuestionLabel || ressource.prefix + ' ' + ressource.label.slice(0,1).toLowerCase() + ressource.label.slice(1);

        return [subject, verbPrefix + verbSufix, ressourceLabel, 'en', currentMonth].join(' ') + '.';
    }

    return {
        restrict: 'E',
        require: 'ngModel',
        replace: true,
        templateUrl: 'partials/foyer/capture-montant-ressource.html',
        scope: {
            individu: '=',
            ressourceType: '=',
            dateDeValeur: '=',
            index: '=',
            form: '=',
        },
        link: function(scope, element, attrs, ngModel) {
            var momentDebutAnnee = moment(scope.dateDeValeur).subtract('years', 1);
            scope.debutAnneeGlissante = momentDebutAnnee.format('MMMM YYYY');
            scope.months = SituationService.getMonths(scope.dateDeValeur);
            scope.currentMonth = moment(scope.dateDeValeur).format('MMMM YYYY');
            scope.isNumber = angular.isNumber;
            scope.onGoingLabel = getOnGoingQuestion(scope.individu, scope.ressourceType, scope.currentMonth);

            function checkSumConsistency() {
                scope.monthsSum = scope.ressource.montantsMensuels.reduce(function(sum, current) {
                    return sum + current;
                }, 0);

                ngModel.$setValidity('valuesConsistency', scope.ressource.montantAnnuel >= scope.monthsSum);
            }

            scope.$watch('ressource.montantsMensuels', checkSumConsistency, true);
            scope.$watch('ressource.montantAnnuel', checkSumConsistency);

            scope.shouldAskDateArretDeTravail = function() {
                // If there is no IJSS the first month, we know the arret de travail is recent and don't need to capture the date.
                return ['indJourMaladie', 'indJourMaladieProf', 'indJourAccidentDuTravail'].indexOf(scope.ressourceType.id) >= 0 && scope.ressource.montantsMensuels[0];
            };

            ngModel.$render = function() {
                scope.ressource = ngModel.$viewValue;
            };
        }
    };
});
<|endoftext|>


<commit_before>module.exports = {
  root: true,
  env: {
    node: true,
  },
  plugins: [
    'graphql',
  ],
  extends: [
    'plugin:vue/essential',
    '@vue/airbnb',
  ],
  parserOptions: {
    parser: 'babel-eslint',
  },
  rules: {
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-underscore-dangle': 'off',
  },
  overrides: [
    {
      files: [
        '**/__tests__/*.{j,t}s?(x)',
        '**/tests/unit/**/*.spec.{j,t}s?(x)',
      ],
      env: {
        jest: true,
      },
    },
    {
      files: ['*.vue'],
      rules: {
        'max-len': 'off',
      },
    },
  ],
  globals: {
    UIkit: true,
  },
};
<commit_msg>Ignore max-len ESLint rule<commit_after>module.exports = {
  root: true,
  env: {
    node: true,
  },
  plugins: [
    'graphql',
  ],
  extends: [
    'plugin:vue/essential',
    '@vue/airbnb',
  ],
  parserOptions: {
    parser: 'babel-eslint',
  },
  rules: {
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-underscore-dangle': 'off',
  },
  overrides: [
    {
      files: [
        '**/__tests__/*.{j,t}s?(x)',
        '**/tests/unit/**/*.spec.{j,t}s?(x)',
      ],
      env: {
        jest: true,
      },
    },
    {
      files: ['*.js', '*.vue'],
      rules: {
        'max-len': 'off',
      },
    },
  ],
  globals: {
    UIkit: true,
  },
};
<|endoftext|>


<commit_before>/*
Copyright 2017 Vector Creations Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

import url from 'url';
import React from 'react';
import MatrixClientPeg from '../../../MatrixClientPeg';
import ScalarAuthClient from '../../../ScalarAuthClient';
import SdkConfig from '../../../SdkConfig';
import Modal from '../../../Modal';
import { _t } from '../../../languageHandler';
import sdk from '../../../index';
import AppPermission from './AppPermission';
import AppWarning from './AppWarning';
import MessageSpinner from './MessageSpinner';
import WidgetUtils from '../../../WidgetUtils';
import dis from '../../../dispatcher';

const ALLOWED_APP_URL_SCHEMES = ['https:', 'http:'];
const betaHelpMsg = 'This feature is currently experimental and is intended for beta testing only';

export default React.createClass({
    displayName: 'AppTile',

    propTypes: {
        id: React.PropTypes.string.isRequired,
        url: React.PropTypes.string.isRequired,
        name: React.PropTypes.string.isRequired,
        room: React.PropTypes.object.isRequired,
        type: React.PropTypes.string.isRequired,
        // Specifying 'fullWidth' as true will render the app tile to fill the width of the app drawer continer.
        // This should be set to true when there is only one widget in the app drawer, otherwise it should be false.
        fullWidth: React.PropTypes.bool,
        // UserId of the current user
        userId: React.PropTypes.string.isRequired,
        // UserId of the entity that added / modified the widget
        creatorUserId: React.PropTypes.string,
    },

    getDefaultProps: function() {
        return {
            url: "",
        };
    },

    getInitialState: function() {
        const widgetPermissionId = [this.props.room.roomId, encodeURIComponent(this.props.url)].join('_');
        const hasPermissionToLoad = localStorage.getItem(widgetPermissionId);
        return {
            loading: false,
            widgetUrl: this.props.url,
            widgetPermissionId: widgetPermissionId,
            // Assume that widget has permission to load if we are the user who added it to the room, or if explicitly granted by the user
            hasPermissionToLoad: hasPermissionToLoad === 'true' || this.props.userId === this.props.creatorUserId,
            error: null,
            deleting: false,
        };
    },

    // Returns true if props.url is a scalar URL, typically https://scalar.vector.im/api
    isScalarUrl: function() {
        const scalarUrl = SdkConfig.get().integrations_rest_url;
        return scalarUrl && this.props.url.startsWith(scalarUrl);
    },

    isMixedContent: function() {
        const parentContentProtocol = window.location.protocol;
        const u = url.parse(this.props.url);
        const childContentProtocol = u.protocol;
        if (parentContentProtocol === 'https:' && childContentProtocol !== 'https:') {
            console.warn("Refusing to load mixed-content app:",
            parentContentProtocol, childContentProtocol, window.location, this.props.url);
            return true;
        }
        return false;
    },

    componentWillMount: function() {
        if (!this.isScalarUrl()) {
            return;
        }
        // Fetch the token before loading the iframe as we need to mangle the URL
        this.setState({
            loading: true,
        });
        this._scalarClient = new ScalarAuthClient();
        this._scalarClient.getScalarToken().done((token) => {
            // Append scalar_token as a query param
            this._scalarClient.scalarToken = token;
            const u = url.parse(this.props.url);
            if (!u.search) {
                u.search = "?scalar_token=" + encodeURIComponent(token);
            } else {
                u.search += "&scalar_token=" + encodeURIComponent(token);
            }

            this.setState({
                error: null,
                widgetUrl: u.format(),
                loading: false,
            });
        }, (err) => {
            this.setState({
                error: err.message,
                loading: false,
            });
        });
    },

    _canUserModify: function() {
        return WidgetUtils.canUserModifyWidgets(this.props.room.roomId);
    },

    _onEditClick: function(e) {
        console.log("Edit widget ID ", this.props.id);
        const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager");
        const src = this._scalarClient.getScalarInterfaceUrlForRoom(this.props.room.roomId, 'type_' + this.props.type);
        Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, {
            src: src,
        }, "mx_IntegrationsManager");
    },

    /* If user has permission to modify widgets, delete the widget, otherwise revoke access for the widget to load in the user's browser
    */
    _onDeleteClick: function() {
        if (this._canUserModify()) {
            console.log("Delete widget %s", this.props.id);
            this.setState({deleting: true});
            MatrixClientPeg.get().sendStateEvent(
                this.props.room.roomId,
                'im.vector.modular.widgets',
                {}, // empty content
                this.props.id,
            ).then(() => {
                console.log('Deleted widget');
            }, (e) => {
                console.error('Failed to delete widget', e);
                this.setState({deleting: false});
            });
        } else {
            console.log("Revoke widget permissions - %s", this.props.id);
            this._revokeWidgetPermission();
        }
    },

    // Widget labels to render, depending upon user permissions
    // These strings are translated at the point that they are inserted in to the DOM, in the render method
    _deleteWidgetLabel() {
        if (this._canUserModify()) {
            return 'Delete widget';
        }
        return 'Revoke widget access';
    },

    /* TODO -- Store permission in account data so that it is persisted across multiple devices */
    _grantWidgetPermission() {
        console.warn('Granting permission to load widget - ', this.state.widgetUrl);
        localStorage.setItem(this.state.widgetPermissionId, true);
        this.setState({hasPermissionToLoad: true});
    },

    _revokeWidgetPermission() {
        console.warn('Revoking permission to load widget - ', this.state.widgetUrl);
        localStorage.removeItem(this.state.widgetPermissionId);
        this.setState({hasPermissionToLoad: false});
    },

    formatAppTileName: function() {
        let appTileName = "No name";
        if(this.props.name && this.props.name.trim()) {
            appTileName = this.props.name.trim();
        }
        return appTileName;
    },

    onClickMenuBar: function(ev) {
        ev.preventDefault();

        // Ignore clicks on menu bar children
        if (ev.target !== this.refs.menu_bar) {
            return;
        }

        // Toggle the view state of the apps drawer
        dis.dispatch({
            action: 'appsDrawer',
            show: !this.props.show,
        });
    },

    render: function() {
        let appTileBody;

        // Don't render widget if it is in the process of being deleted
        if (this.state.deleting) {
            return

;
        }

        // Note that there is advice saying allow-scripts shouldn't be used with allow-same-origin
        // because that would allow the iframe to prgramatically remove the sandbox attribute, but
        // this would only be for content hosted on the same origin as the riot client: anything
        // hosted on the same origin as the client will get the same access as if you clicked
        // a link to it.
        const sandboxFlags = "allow-forms allow-popups allow-popups-to-escape-sandbox "+
            "allow-same-origin allow-scripts allow-presentation";
        const parsedWidgetUrl = url.parse(this.state.widgetUrl);
        let safeWidgetUrl = '';
        if (ALLOWED_APP_URL_SCHEMES.indexOf(parsedWidgetUrl.protocol) !== -1) {
            safeWidgetUrl = url.format(parsedWidgetUrl);
        }

        if (this.props.show) {
            if (this.state.loading) {
                appTileBody = (

                        <MessageSpinner msg='Loading...'/>

                );
            } else if (this.state.hasPermissionToLoad == true) {
                if (this.isMixedContent()) {
                    appTileBody = (

                            <AppWarning
                                errorMsg="Error - Mixed content"
                            />

                    );
                } else {
                    appTileBody = (

                    );
                }
            } else {
                const isRoomEncrypted = MatrixClientPeg.get().isRoomEncrypted(this.props.room.roomId);
                appTileBody = (

                        <AppPermission
                            isRoomEncrypted={isRoomEncrypted}
                            url={this.state.widgetUrl}
                            onPermissionGranted={this._grantWidgetPermission}
                        />

                );
            }
        }

        // editing is done in scalar
        const showEditButton = Boolean(this._scalarClient && this._canUserModify());
        const deleteWidgetLabel = this._deleteWidgetLabel();
        let deleteIcon = 'img/cancel.svg';
        let deleteClasses = 'mx_filterFlipColor mx_AppTileMenuBarWidget';
        if(this._canUserModify()) {
            deleteIcon = 'img/cancel-red.svg';
            deleteClasses += ' mx_AppTileMenuBarWidgetDelete';
        }

        return (

                    {this.formatAppTileName()}

                        β
                        {/* Edit widget */}
                        {showEditButton && }

                        {/* Delete widget */}

                {appTileBody}

        );
    },
});
<commit_msg>Remove beta tag.<commit_after>/*
Copyright 2017 Vector Creations Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

import url from 'url';
import React from 'react';
import MatrixClientPeg from '../../../MatrixClientPeg';
import ScalarAuthClient from '../../../ScalarAuthClient';
import SdkConfig from '../../../SdkConfig';
import Modal from '../../../Modal';
import { _t } from '../../../languageHandler';
import sdk from '../../../index';
import AppPermission from './AppPermission';
import AppWarning from './AppWarning';
import MessageSpinner from './MessageSpinner';
import WidgetUtils from '../../../WidgetUtils';
import dis from '../../../dispatcher';

const ALLOWED_APP_URL_SCHEMES = ['https:', 'http:'];

export default React.createClass({
    displayName: 'AppTile',

    propTypes: {
        id: React.PropTypes.string.isRequired,
        url: React.PropTypes.string.isRequired,
        name: React.PropTypes.string.isRequired,
        room: React.PropTypes.object.isRequired,
        type: React.PropTypes.string.isRequired,
        // Specifying 'fullWidth' as true will render the app tile to fill the width of the app drawer continer.
        // This should be set to true when there is only one widget in the app drawer, otherwise it should be false.
        fullWidth: React.PropTypes.bool,
        // UserId of the current user
        userId: React.PropTypes.string.isRequired,
        // UserId of the entity that added / modified the widget
        creatorUserId: React.PropTypes.string,
    },

    getDefaultProps: function() {
        return {
            url: "",
        };
    },

    getInitialState: function() {
        const widgetPermissionId = [this.props.room.roomId, encodeURIComponent(this.props.url)].join('_');
        const hasPermissionToLoad = localStorage.getItem(widgetPermissionId);
        return {
            loading: false,
            widgetUrl: this.props.url,
            widgetPermissionId: widgetPermissionId,
            // Assume that widget has permission to load if we are the user who added it to the room, or if explicitly granted by the user
            hasPermissionToLoad: hasPermissionToLoad === 'true' || this.props.userId === this.props.creatorUserId,
            error: null,
            deleting: false,
        };
    },

    // Returns true if props.url is a scalar URL, typically https://scalar.vector.im/api
    isScalarUrl: function() {
        const scalarUrl = SdkConfig.get().integrations_rest_url;
        return scalarUrl && this.props.url.startsWith(scalarUrl);
    },

    isMixedContent: function() {
        const parentContentProtocol = window.location.protocol;
        const u = url.parse(this.props.url);
        const childContentProtocol = u.protocol;
        if (parentContentProtocol === 'https:' && childContentProtocol !== 'https:') {
            console.warn("Refusing to load mixed-content app:",
            parentContentProtocol, childContentProtocol, window.location, this.props.url);
            return true;
        }
        return false;
    },

    componentWillMount: function() {
        if (!this.isScalarUrl()) {
            return;
        }
        // Fetch the token before loading the iframe as we need to mangle the URL
        this.setState({
            loading: true,
        });
        this._scalarClient = new ScalarAuthClient();
        this._scalarClient.getScalarToken().done((token) => {
            // Append scalar_token as a query param
            this._scalarClient.scalarToken = token;
            const u = url.parse(this.props.url);
            if (!u.search) {
                u.search = "?scalar_token=" + encodeURIComponent(token);
            } else {
                u.search += "&scalar_token=" + encodeURIComponent(token);
            }

            this.setState({
                error: null,
                widgetUrl: u.format(),
                loading: false,
            });
        }, (err) => {
            this.setState({
                error: err.message,
                loading: false,
            });
        });
    },

    _canUserModify: function() {
        return WidgetUtils.canUserModifyWidgets(this.props.room.roomId);
    },

    _onEditClick: function(e) {
        console.log("Edit widget ID ", this.props.id);
        const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager");
        const src = this._scalarClient.getScalarInterfaceUrlForRoom(this.props.room.roomId, 'type_' + this.props.type);
        Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, {
            src: src,
        }, "mx_IntegrationsManager");
    },

    /* If user has permission to modify widgets, delete the widget, otherwise revoke access for the widget to load in the user's browser
    */
    _onDeleteClick: function() {
        if (this._canUserModify()) {
            console.log("Delete widget %s", this.props.id);
            this.setState({deleting: true});
            MatrixClientPeg.get().sendStateEvent(
                this.props.room.roomId,
                'im.vector.modular.widgets',
                {}, // empty content
                this.props.id,
            ).then(() => {
                console.log('Deleted widget');
            }, (e) => {
                console.error('Failed to delete widget', e);
                this.setState({deleting: false});
            });
        } else {
            console.log("Revoke widget permissions - %s", this.props.id);
            this._revokeWidgetPermission();
        }
    },

    // Widget labels to render, depending upon user permissions
    // These strings are translated at the point that they are inserted in to the DOM, in the render method
    _deleteWidgetLabel() {
        if (this._canUserModify()) {
            return 'Delete widget';
        }
        return 'Revoke widget access';
    },

    /* TODO -- Store permission in account data so that it is persisted across multiple devices */
    _grantWidgetPermission() {
        console.warn('Granting permission to load widget - ', this.state.widgetUrl);
        localStorage.setItem(this.state.widgetPermissionId, true);
        this.setState({hasPermissionToLoad: true});
    },

    _revokeWidgetPermission() {
        console.warn('Revoking permission to load widget - ', this.state.widgetUrl);
        localStorage.removeItem(this.state.widgetPermissionId);
        this.setState({hasPermissionToLoad: false});
    },

    formatAppTileName: function() {
        let appTileName = "No name";
        if(this.props.name && this.props.name.trim()) {
            appTileName = this.props.name.trim();
        }
        return appTileName;
    },

    onClickMenuBar: function(ev) {
        ev.preventDefault();

        // Ignore clicks on menu bar children
        if (ev.target !== this.refs.menu_bar) {
            return;
        }

        // Toggle the view state of the apps drawer
        dis.dispatch({
            action: 'appsDrawer',
            show: !this.props.show,
        });
    },

    render: function() {
        let appTileBody;

        // Don't render widget if it is in the process of being deleted
        if (this.state.deleting) {
            return

;
        }

        // Note that there is advice saying allow-scripts shouldn't be used with allow-same-origin
        // because that would allow the iframe to prgramatically remove the sandbox attribute, but
        // this would only be for content hosted on the same origin as the riot client: anything
        // hosted on the same origin as the client will get the same access as if you clicked
        // a link to it.
        const sandboxFlags = "allow-forms allow-popups allow-popups-to-escape-sandbox "+
            "allow-same-origin allow-scripts allow-presentation";
        const parsedWidgetUrl = url.parse(this.state.widgetUrl);
        let safeWidgetUrl = '';
        if (ALLOWED_APP_URL_SCHEMES.indexOf(parsedWidgetUrl.protocol) !== -1) {
            safeWidgetUrl = url.format(parsedWidgetUrl);
        }

        if (this.props.show) {
            if (this.state.loading) {
                appTileBody = (

                        <MessageSpinner msg='Loading...'/>

                );
            } else if (this.state.hasPermissionToLoad == true) {
                if (this.isMixedContent()) {
                    appTileBody = (

                            <AppWarning
                                errorMsg="Error - Mixed content"
                            />

                    );
                } else {
                    appTileBody = (

                    );
                }
            } else {
                const isRoomEncrypted = MatrixClientPeg.get().isRoomEncrypted(this.props.room.roomId);
                appTileBody = (

                        <AppPermission
                            isRoomEncrypted={isRoomEncrypted}
                            url={this.state.widgetUrl}
                            onPermissionGranted={this._grantWidgetPermission}
                        />

                );
            }
        }

        // editing is done in scalar
        const showEditButton = Boolean(this._scalarClient && this._canUserModify());
        const deleteWidgetLabel = this._deleteWidgetLabel();
        let deleteIcon = 'img/cancel.svg';
        let deleteClasses = 'mx_filterFlipColor mx_AppTileMenuBarWidget';
        if(this._canUserModify()) {
            deleteIcon = 'img/cancel-red.svg';
            deleteClasses += ' mx_AppTileMenuBarWidgetDelete';
        }

        return (

                    {this.formatAppTileName()}

                        {/* Edit widget */}
                        {showEditButton && }

                        {/* Delete widget */}

                {appTileBody}

        );
    },
});
<|endoftext|>


<commit_before>export default [{
  register: require('good'),
  options: {
    reporters: [{
      reporter: 'good-console',
      events: {
        log: '*',
        response: '*',
        error: '*'
      }
    }]
  }
}, {
  register: require('hapi-auth-bearer-token')
}];
<commit_msg>Forgot to require auth-ownership as a plugin<commit_after>export default [{
  register: require('good'),
  options: {
    reporters: [{
      reporter: 'good-console',
      events: {
        log: '*',
        response: '*',
        error: '*'
      }
    }]
  }
}, {
  register: require('hapi-auth-bearer-token')
}, {
  register: require('../plugins/auth-ownership')
}];
<|endoftext|>


<commit_before>/* Base Pattern
 */

define([
  'jquery',
  'pat-registry',
  'mockup-parser',
  "pat-logger"
], function($, Registry, mockupParser, logger) {
  'use strict';
  var log = logger.getLogger("Mockup Base");

  var initMockup = function initMockup($el, options, trigger) {
    var name = this.prototype.name;
    var log = logger.getLogger("pat." + name);
    var pattern = $el.data('pattern-' + name);
    if (pattern === undefined && Registry.patterns[name]) {
      options = this.prototype.parser === "mockup" ? mockupParser.getOptions($el, name, options) : options;
      try {
          pattern = new Registry.patterns[name]($el, options);
      } catch (e) {
          log.error('Failed while initializing "' + name + '" pattern.', e);
      }
      $el.data('pattern-' + name, pattern);
    }
    return pattern;
  };

  // Base Pattern
  var Base = function($el, options) {
    function _recursiveExtend(obj, source){
      if (typeof source === "object" && source !== null){
        for (var p in source){
          if ($.isArray(source[p])){
            obj[p] = source[p];
          } else if (typeof source[p] === "object" && source[p] !== null){
            // This is another dict, so will recurse
            if (!obj.hasOwnProperty(p) || typeof obj[p] !== "object"){
              // Create if not there, or if it is something else
              obj[p] = {};
            }
            _recursiveExtend(obj[p], source[p]);
          } else {
            obj[p] = source[p];
          }
        }
      }
    }

    this.$el = $el;
    this.options = this.defaults || {};
    _recursiveExtend(this.options, options);
    this.init($el, options);
    this.emit('init');
  };

  Base.prototype = {
    constructor: Base,
    on: function(eventName, eventCallback) {
      this.$el.on(eventName + '.' + this.name + '.patterns', eventCallback);
    },
    emit: function(eventName, args) {
      // args should be a list
      if (args === undefined) {
        args = [];
      }
      this.$el.trigger(eventName + '.' + this.name + '.patterns', args);
    }
  };

  Base.extend = function(patternProps) {
    /* Helper function to correctly set up the prototype chain for new patterns.
     */
    var parent = this;
    var child;

    // Check that the required configuration properties are given.
    if (!patternProps) {
      throw new Error("Pattern configuration properties required when calling Base.extend");
    }

    // The constructor function for the new subclass is either defined by you
    // (the "constructor" property in your `extend` definition), or defaulted
    // by us to simply call the parent's constructor.
    if (patternProps.hasOwnProperty('constructor')) {
      child = patternProps.constructor;
    } else {
      child = function() { parent.apply(this, arguments); };
    }

    // Allow patterns to be extended indefinitely
    child.extend = Base.extend;

    // Static properties required by the Patternslib registry
    child.init = initMockup;
    child.jquery_plugin = true;
    child.trigger = patternProps.trigger;

    // Set the prototype chain to inherit from `parent`, without calling
    // `parent`'s constructor function.
    var Surrogate = function() { this.constructor = child; };
    Surrogate.prototype = parent.prototype;
    child.prototype = new Surrogate();

    // Fall back to mockup parser if not specified otherwise.
    patternProps.parser = patternProps.parser || 'mockup';

    // Add pattern's configuration properties (instance properties) to the subclass,
    $.extend(true, child.prototype, patternProps);

    // Set a convenience property in case the parent's prototype is needed
    // later.
    child.__super__ = parent.prototype;

    // Register the pattern in the Patternslib registry.
    if (!patternProps.name) {
      log.warn("This mockup pattern without a name attribute will not be registered!");
    } else if (!patternProps.trigger) {
      log.warn("The mockup pattern '"+patternProps.name+"' does not have a trigger attribute, it will not be registered.");
    } else {
      Registry.register(child, patternProps.name);
    }
    return child;
  };
  return Base;
});
<commit_msg>We actually need this.options to be a new object<commit_after>/* Base Pattern
 */

define([
  'jquery',
  'pat-registry',
  'mockup-parser',
  "pat-logger"
], function($, Registry, mockupParser, logger) {
  'use strict';
  var log = logger.getLogger("Mockup Base");

  var initMockup = function initMockup($el, options, trigger) {
    var name = this.prototype.name;
    var log = logger.getLogger("pat." + name);
    var pattern = $el.data('pattern-' + name);
    if (pattern === undefined && Registry.patterns[name]) {
      options = this.prototype.parser === "mockup" ? mockupParser.getOptions($el, name, options) : options;
      try {
          pattern = new Registry.patterns[name]($el, options);
      } catch (e) {
          log.error('Failed while initializing "' + name + '" pattern.', e);
      }
      $el.data('pattern-' + name, pattern);
    }
    return pattern;
  };

  // Base Pattern
  var Base = function($el, options) {
    function _recursiveExtend(obj, source){
      if (typeof source === "object" && source !== null){
        for (var p in source){
          if ($.isArray(source[p])){
            obj[p] = source[p];
          } else if (typeof source[p] === "object" && source[p] !== null){
            // This is another dict, so will recurse
            if (!obj.hasOwnProperty(p) || typeof obj[p] !== "object"){
              // Create if not there, or if it is something else
              obj[p] = {};
            }
            _recursiveExtend(obj[p], source[p]);
          } else {
            obj[p] = source[p];
          }
        }
      }
    }

    this.$el = $el;
    this.options = $.extend(true, {}, this.defaults || {});
    _recursiveExtend(this.options, options);
    this.init($el, options);
    this.emit('init');
  };

  Base.prototype = {
    constructor: Base,
    on: function(eventName, eventCallback) {
      this.$el.on(eventName + '.' + this.name + '.patterns', eventCallback);
    },
    emit: function(eventName, args) {
      // args should be a list
      if (args === undefined) {
        args = [];
      }
      this.$el.trigger(eventName + '.' + this.name + '.patterns', args);
    }
  };

  Base.extend = function(patternProps) {
    /* Helper function to correctly set up the prototype chain for new patterns.
     */
    var parent = this;
    var child;

    // Check that the required configuration properties are given.
    if (!patternProps) {
      throw new Error("Pattern configuration properties required when calling Base.extend");
    }

    // The constructor function for the new subclass is either defined by you
    // (the "constructor" property in your `extend` definition), or defaulted
    // by us to simply call the parent's constructor.
    if (patternProps.hasOwnProperty('constructor')) {
      child = patternProps.constructor;
    } else {
      child = function() { parent.apply(this, arguments); };
    }

    // Allow patterns to be extended indefinitely
    child.extend = Base.extend;

    // Static properties required by the Patternslib registry
    child.init = initMockup;
    child.jquery_plugin = true;
    child.trigger = patternProps.trigger;

    // Set the prototype chain to inherit from `parent`, without calling
    // `parent`'s constructor function.
    var Surrogate = function() { this.constructor = child; };
    Surrogate.prototype = parent.prototype;
    child.prototype = new Surrogate();

    // Fall back to mockup parser if not specified otherwise.
    patternProps.parser = patternProps.parser || 'mockup';

    // Add pattern's configuration properties (instance properties) to the subclass,
    $.extend(true, child.prototype, patternProps);

    // Set a convenience property in case the parent's prototype is needed
    // later.
    child.__super__ = parent.prototype;

    // Register the pattern in the Patternslib registry.
    if (!patternProps.name) {
      log.warn("This mockup pattern without a name attribute will not be registered!");
    } else if (!patternProps.trigger) {
      log.warn("The mockup pattern '"+patternProps.name+"' does not have a trigger attribute, it will not be registered.");
    } else {
      Registry.register(child, patternProps.name);
    }
    return child;
  };
  return Base;
});
<|endoftext|>