Commit 7c7f7b2a authored by Jason Song's avatar Jason Song

format according google code style

parent d25e0cbf
...@@ -2,7 +2,6 @@ package com.ctrip.apollo; ...@@ -2,7 +2,6 @@ package com.ctrip.apollo;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication @SpringBootApplication
......
...@@ -2,6 +2,7 @@ package com.ctrip.apollo.adminservice.controller; ...@@ -2,6 +2,7 @@ package com.ctrip.apollo.adminservice.controller;
import com.ctrip.apollo.biz.service.AdminConfigService; import com.ctrip.apollo.biz.service.AdminConfigService;
import com.ctrip.apollo.core.dto.ClusterDTO; import com.ctrip.apollo.core.dto.ClusterDTO;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
...@@ -17,7 +18,7 @@ public class ClusterController { ...@@ -17,7 +18,7 @@ public class ClusterController {
private AdminConfigService adminConfigService; private AdminConfigService adminConfigService;
@RequestMapping("/app/{appId}") @RequestMapping("/app/{appId}")
public List<ClusterDTO> findClustersByApp(@PathVariable long appId){ public List<ClusterDTO> findClustersByApp(@PathVariable long appId) {
return adminConfigService.findClustersByApp(appId); return adminConfigService.findClustersByApp(appId);
} }
} }
...@@ -3,14 +3,16 @@ package com.ctrip.apollo.adminservice.controller; ...@@ -3,14 +3,16 @@ package com.ctrip.apollo.adminservice.controller;
import com.ctrip.apollo.biz.service.AdminConfigService; import com.ctrip.apollo.biz.service.AdminConfigService;
import com.ctrip.apollo.core.dto.ConfigItemDTO; import com.ctrip.apollo.core.dto.ConfigItemDTO;
import com.ctrip.apollo.core.dto.ReleaseSnapshotDTO; import com.ctrip.apollo.core.dto.ReleaseSnapshotDTO;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List; import java.util.List;
import javax.annotation.Resource;
@RestController @RestController
@RequestMapping("/configs") @RequestMapping("/configs")
public class ConfigController { public class ConfigController {
...@@ -20,12 +22,13 @@ public class ConfigController { ...@@ -20,12 +22,13 @@ public class ConfigController {
@RequestMapping("/release/{releaseId}") @RequestMapping("/release/{releaseId}")
public List<ReleaseSnapshotDTO> getRelaseSnapshot(@PathVariable long releaseId){ public List<ReleaseSnapshotDTO> getRelaseSnapshot(@PathVariable long releaseId) {
return adminConfigService.findReleaseSnapshotByReleaseId(releaseId); return adminConfigService.findReleaseSnapshotByReleaseId(releaseId);
} }
@RequestMapping("/latest") @RequestMapping("/latest")
public List<ConfigItemDTO> findConfigItemsByClusters(@RequestParam(value = "clusterIds") List<Long> clusterIds){ public List<ConfigItemDTO> findConfigItemsByClusters(
@RequestParam(value = "clusterIds") List<Long> clusterIds) {
return adminConfigService.findConfigItemsByClusters(clusterIds); return adminConfigService.findConfigItemsByClusters(clusterIds);
} }
......
...@@ -2,6 +2,7 @@ package com.ctrip.apollo.adminservice.controller; ...@@ -2,6 +2,7 @@ package com.ctrip.apollo.adminservice.controller;
import com.ctrip.apollo.biz.service.AdminConfigService; import com.ctrip.apollo.biz.service.AdminConfigService;
import com.ctrip.apollo.core.dto.VersionDTO; import com.ctrip.apollo.core.dto.VersionDTO;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
...@@ -17,17 +18,15 @@ public class VersionController { ...@@ -17,17 +18,15 @@ public class VersionController {
private AdminConfigService adminConfigService; private AdminConfigService adminConfigService;
@RequestMapping("/app/{appId}") @RequestMapping("/app/{appId}")
public List<VersionDTO> versions(@PathVariable long appId){ public List<VersionDTO> versions(@PathVariable long appId) {
return adminConfigService.findVersionsByApp(appId); return adminConfigService.findVersionsByApp(appId);
} }
@RequestMapping("/{versionId}") @RequestMapping("/{versionId}")
public VersionDTO version(@PathVariable long versionId){ public VersionDTO version(@PathVariable long versionId) {
return adminConfigService.loadVersionById(versionId); return adminConfigService.loadVersionById(versionId);
} }
} }
package com.ctrip.apollo.biz.entity; package com.ctrip.apollo.biz.entity;
import com.ctrip.apollo.core.dto.ClusterDTO; import com.ctrip.apollo.core.dto.ClusterDTO;
import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where; import org.hibernate.annotations.Where;
...@@ -63,7 +64,7 @@ public class Cluster { ...@@ -63,7 +64,7 @@ public class Cluster {
isDeleted = deleted; isDeleted = deleted;
} }
public ClusterDTO toDTO(){ public ClusterDTO toDTO() {
ClusterDTO dto = new ClusterDTO(); ClusterDTO dto = new ClusterDTO();
dto.setAppId(appId); dto.setAppId(appId);
dto.setId(id); dto.setId(id);
......
package com.ctrip.apollo.biz.entity; package com.ctrip.apollo.biz.entity;
import com.ctrip.apollo.core.dto.ConfigItemDTO; import com.ctrip.apollo.core.dto.ConfigItemDTO;
import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where; import org.hibernate.annotations.Where;
import java.util.Date;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.GeneratedValue; import javax.persistence.GeneratedValue;
import javax.persistence.Id; import javax.persistence.Id;
import java.util.Date;
@Entity @Entity
@Where(clause = "isDeleted = 0") @Where(clause = "isDeleted = 0")
...@@ -148,7 +150,7 @@ public class ConfigItem { ...@@ -148,7 +150,7 @@ public class ConfigItem {
this.dataChangeLastModifiedTime = dataChangeLastModifiedTime; this.dataChangeLastModifiedTime = dataChangeLastModifiedTime;
} }
public ConfigItemDTO toDTO(){ public ConfigItemDTO toDTO() {
ConfigItemDTO dto = new ConfigItemDTO(); ConfigItemDTO dto = new ConfigItemDTO();
dto.setAppId(appId); dto.setAppId(appId);
dto.setId(id); dto.setId(id);
......
package com.ctrip.apollo.biz.entity; package com.ctrip.apollo.biz.entity;
import com.ctrip.apollo.core.dto.ReleaseSnapshotDTO; import com.ctrip.apollo.core.dto.ReleaseSnapshotDTO;
import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where; import org.hibernate.annotations.Where;
...@@ -74,7 +75,7 @@ public class ReleaseSnapShot { ...@@ -74,7 +75,7 @@ public class ReleaseSnapShot {
isDeleted = deleted; isDeleted = deleted;
} }
public ReleaseSnapshotDTO toDTO(){ public ReleaseSnapshotDTO toDTO() {
ReleaseSnapshotDTO dto = new ReleaseSnapshotDTO(); ReleaseSnapshotDTO dto = new ReleaseSnapshotDTO();
dto.setId(id); dto.setId(id);
dto.setClusterName(clusterName); dto.setClusterName(clusterName);
......
package com.ctrip.apollo.biz.entity; package com.ctrip.apollo.biz.entity;
import com.ctrip.apollo.core.dto.VersionDTO; import com.ctrip.apollo.core.dto.VersionDTO;
import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where; import org.hibernate.annotations.Where;
......
...@@ -2,6 +2,7 @@ package com.ctrip.apollo.biz.repository; ...@@ -2,6 +2,7 @@ package com.ctrip.apollo.biz.repository;
import com.ctrip.apollo.biz.entity.Cluster; import com.ctrip.apollo.biz.entity.Cluster;
import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.PagingAndSortingRepository;
import java.util.List; import java.util.List;
......
package com.ctrip.apollo.biz.repository; package com.ctrip.apollo.biz.repository;
import com.ctrip.apollo.biz.entity.ConfigItem; import com.ctrip.apollo.biz.entity.ConfigItem;
import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.PagingAndSortingRepository;
import java.util.List; import java.util.List;
......
package com.ctrip.apollo.biz.repository; package com.ctrip.apollo.biz.repository;
import com.ctrip.apollo.biz.entity.ReleaseSnapShot; import com.ctrip.apollo.biz.entity.ReleaseSnapShot;
import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.PagingAndSortingRepository;
import java.util.List; import java.util.List;
...@@ -8,7 +9,8 @@ import java.util.List; ...@@ -8,7 +9,8 @@ import java.util.List;
/** /**
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
*/ */
public interface ReleaseSnapShotRepository extends PagingAndSortingRepository<ReleaseSnapShot, Long> { public interface ReleaseSnapShotRepository
extends PagingAndSortingRepository<ReleaseSnapShot, Long> {
ReleaseSnapShot findByReleaseIdAndClusterName(long releaseId, String clusterName); ReleaseSnapShot findByReleaseIdAndClusterName(long releaseId, String clusterName);
List<ReleaseSnapShot> findByReleaseId(long releaseId); List<ReleaseSnapShot> findByReleaseId(long releaseId);
......
package com.ctrip.apollo.biz.repository; package com.ctrip.apollo.biz.repository;
import com.ctrip.apollo.biz.entity.Version; import com.ctrip.apollo.biz.entity.Version;
import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.PagingAndSortingRepository;
import java.util.List; import java.util.List;
......
package com.ctrip.apollo.biz.service; package com.ctrip.apollo.biz.service;
import com.ctrip.apollo.core.dto.*; import com.ctrip.apollo.core.dto.ClusterDTO;
import com.ctrip.apollo.core.dto.ConfigItemDTO;
import com.ctrip.apollo.core.dto.ReleaseSnapshotDTO;
import com.ctrip.apollo.core.dto.VersionDTO;
import java.util.List; import java.util.List;
......
...@@ -5,31 +5,22 @@ import com.ctrip.apollo.core.dto.ApolloConfig; ...@@ -5,31 +5,22 @@ import com.ctrip.apollo.core.dto.ApolloConfig;
/** /**
* Config Service * Config Service
*
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
*/ */
public interface ConfigService { public interface ConfigService {
/** /**
* Load configuration from database * Load configuration from database
* @param appId
* @param clusterName
* @param versionName
* @return
*/ */
ApolloConfig loadConfig(long appId, String clusterName, String versionName); ApolloConfig loadConfig(long appId, String clusterName, String versionName);
/** /**
* Load Version by appId and versionName from database * Load Version by appId and versionName from database
* @param appId
* @param versionName
* @return
*/ */
Version loadVersionByAppIdAndVersionName(long appId, String versionName); Version loadVersionByAppIdAndVersionName(long appId, String versionName);
/** /**
* Load Config by version and clusterName from database * Load Config by version and clusterName from database
* @param version
* @param clusterName
* @return
*/ */
ApolloConfig loadConfigByVersionAndClusterName(Version version, String clusterName); ApolloConfig loadConfigByVersionAndClusterName(Version version, String clusterName);
} }
...@@ -9,11 +9,17 @@ import com.ctrip.apollo.biz.repository.ConfigItemRepository; ...@@ -9,11 +9,17 @@ import com.ctrip.apollo.biz.repository.ConfigItemRepository;
import com.ctrip.apollo.biz.repository.ReleaseSnapShotRepository; import com.ctrip.apollo.biz.repository.ReleaseSnapShotRepository;
import com.ctrip.apollo.biz.repository.VersionRepository; import com.ctrip.apollo.biz.repository.VersionRepository;
import com.ctrip.apollo.biz.service.AdminConfigService; import com.ctrip.apollo.biz.service.AdminConfigService;
import com.ctrip.apollo.core.dto.*; import com.ctrip.apollo.core.dto.ClusterDTO;
import com.ctrip.apollo.core.dto.ConfigItemDTO;
import com.ctrip.apollo.core.dto.ReleaseSnapshotDTO;
import com.ctrip.apollo.core.dto.VersionDTO;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.*; import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Service("adminConfigService") @Service("adminConfigService")
public class AdminConfigServiceImpl implements AdminConfigService { public class AdminConfigServiceImpl implements AdminConfigService {
...@@ -29,18 +35,18 @@ public class AdminConfigServiceImpl implements AdminConfigService { ...@@ -29,18 +35,18 @@ public class AdminConfigServiceImpl implements AdminConfigService {
@Override @Override
public List<ReleaseSnapshotDTO> findReleaseSnapshotByReleaseId(long releaseId) { public List<ReleaseSnapshotDTO> findReleaseSnapshotByReleaseId(long releaseId) {
if (releaseId <= 0){ if (releaseId <= 0) {
return Collections.EMPTY_LIST; return Collections.EMPTY_LIST;
} }
List<ReleaseSnapShot> releaseSnapShots = releaseSnapShotRepository.findByReleaseId(releaseId); List<ReleaseSnapShot> releaseSnapShots = releaseSnapShotRepository.findByReleaseId(releaseId);
if (releaseSnapShots == null || releaseSnapShots.size() == 0){ if (releaseSnapShots == null || releaseSnapShots.size() == 0) {
return Collections.EMPTY_LIST; return Collections.EMPTY_LIST;
} }
List<ReleaseSnapshotDTO> result = new ArrayList<>(releaseSnapShots.size()); List<ReleaseSnapshotDTO> result = new ArrayList<>(releaseSnapShots.size());
for (ReleaseSnapShot releaseSnapShot: releaseSnapShots){ for (ReleaseSnapShot releaseSnapShot : releaseSnapShots) {
result.add(releaseSnapShot.toDTO()); result.add(releaseSnapShot.toDTO());
} }
return result; return result;
...@@ -67,7 +73,7 @@ public class AdminConfigServiceImpl implements AdminConfigService { ...@@ -67,7 +73,7 @@ public class AdminConfigServiceImpl implements AdminConfigService {
@Override @Override
public VersionDTO loadVersionById(long versionId) { public VersionDTO loadVersionById(long versionId) {
if (versionId <= 0){ if (versionId <= 0) {
return null; return null;
} }
Version version = versionRepository.findById(versionId); Version version = versionRepository.findById(versionId);
...@@ -76,16 +82,16 @@ public class AdminConfigServiceImpl implements AdminConfigService { ...@@ -76,16 +82,16 @@ public class AdminConfigServiceImpl implements AdminConfigService {
@Override @Override
public List<ClusterDTO> findClustersByApp(long appId) { public List<ClusterDTO> findClustersByApp(long appId) {
if (appId <= 0){ if (appId <= 0) {
return Collections.EMPTY_LIST; return Collections.EMPTY_LIST;
} }
List<Cluster> clusters = clusterRepository.findByAppId(appId); List<Cluster> clusters = clusterRepository.findByAppId(appId);
if (clusters == null || clusters.size() == 0){ if (clusters == null || clusters.size() == 0) {
return Collections.EMPTY_LIST; return Collections.EMPTY_LIST;
} }
List<ClusterDTO> result = new ArrayList<>(clusters.size()); List<ClusterDTO> result = new ArrayList<>(clusters.size());
for (Cluster cluster: clusters){ for (Cluster cluster : clusters) {
result.add(cluster.toDTO()); result.add(cluster.toDTO());
} }
return result; return result;
...@@ -93,16 +99,16 @@ public class AdminConfigServiceImpl implements AdminConfigService { ...@@ -93,16 +99,16 @@ public class AdminConfigServiceImpl implements AdminConfigService {
@Override @Override
public List<ConfigItemDTO> findConfigItemsByClusters(List<Long> clusterIds) { public List<ConfigItemDTO> findConfigItemsByClusters(List<Long> clusterIds) {
if (clusterIds == null || clusterIds.size() == 0){ if (clusterIds == null || clusterIds.size() == 0) {
return Collections.EMPTY_LIST; return Collections.EMPTY_LIST;
} }
List<ConfigItem> configItems = configItemRepository.findByClusterIdIsIn(clusterIds); List<ConfigItem> configItems = configItemRepository.findByClusterIdIsIn(clusterIds);
if (configItems == null || configItems.size() == 0){ if (configItems == null || configItems.size() == 0) {
return Collections.EMPTY_LIST; return Collections.EMPTY_LIST;
} }
List<ConfigItemDTO> result = new ArrayList<>(configItems.size()); List<ConfigItemDTO> result = new ArrayList<>(configItems.size());
for (ConfigItem configItem: configItems){ for (ConfigItem configItem : configItems) {
result.add(configItem.toDTO()); result.add(configItem.toDTO());
} }
return result; return result;
......
package com.ctrip.apollo.biz.service.impl; package com.ctrip.apollo.biz.service.impl;
import com.google.common.collect.Maps;
import com.ctrip.apollo.biz.entity.ReleaseSnapShot; import com.ctrip.apollo.biz.entity.ReleaseSnapShot;
import com.ctrip.apollo.biz.entity.Version; import com.ctrip.apollo.biz.entity.Version;
import com.ctrip.apollo.biz.repository.ReleaseSnapShotRepository; import com.ctrip.apollo.biz.repository.ReleaseSnapShotRepository;
...@@ -8,7 +10,7 @@ import com.ctrip.apollo.biz.service.ConfigService; ...@@ -8,7 +10,7 @@ import com.ctrip.apollo.biz.service.ConfigService;
import com.ctrip.apollo.core.dto.ApolloConfig; import com.ctrip.apollo.core.dto.ApolloConfig;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -48,7 +50,8 @@ public class ConfigServiceImpl implements ConfigService { ...@@ -48,7 +50,8 @@ public class ConfigServiceImpl implements ConfigService {
@Override @Override
public ApolloConfig loadConfigByVersionAndClusterName(Version version, String clusterName) { public ApolloConfig loadConfigByVersionAndClusterName(Version version, String clusterName) {
ReleaseSnapShot releaseSnapShot = ReleaseSnapShot releaseSnapShot =
releaseSnapShotRepository.findByReleaseIdAndClusterName(version.getReleaseId(), clusterName); releaseSnapShotRepository
.findByReleaseIdAndClusterName(version.getReleaseId(), clusterName);
if (releaseSnapShot == null) { if (releaseSnapShot == null) {
return null; return null;
} }
...@@ -58,7 +61,8 @@ public class ConfigServiceImpl implements ConfigService { ...@@ -58,7 +61,8 @@ public class ConfigServiceImpl implements ConfigService {
private ApolloConfig assembleConfig(Version version, ReleaseSnapShot releaseSnapShot) { private ApolloConfig assembleConfig(Version version, ReleaseSnapShot releaseSnapShot) {
ApolloConfig config = ApolloConfig config =
new ApolloConfig(version.getAppId(), releaseSnapShot.getClusterName(), version.getName(), version.getReleaseId()); new ApolloConfig(version.getAppId(), releaseSnapShot.getClusterName(), version.getName(),
version.getReleaseId());
config.setConfigurations(transformConfigurationToMap(releaseSnapShot.getConfigurations())); config.setConfigurations(transformConfigurationToMap(releaseSnapShot.getConfigurations()));
return config; return config;
......
package com.ctrip.apollo.biz; package com.ctrip.apollo.biz;
import com.ctrip.apollo.biz.service.impl.ConfigServiceImplTest; import com.ctrip.apollo.biz.service.impl.ConfigServiceImplTest;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.Suite; import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses; import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class) @RunWith(Suite.class)
@SuiteClasses({ @SuiteClasses({
ConfigServiceImplTest.class}) ConfigServiceImplTest.class})
public class AllTests { public class AllTests {
} }
package com.ctrip.apollo.biz.service.impl; package com.ctrip.apollo.biz.service.impl;
import com.google.common.collect.Maps;
import com.ctrip.apollo.biz.entity.ReleaseSnapShot; import com.ctrip.apollo.biz.entity.ReleaseSnapShot;
import com.ctrip.apollo.biz.entity.Version; import com.ctrip.apollo.biz.entity.Version;
import com.ctrip.apollo.biz.repository.ReleaseSnapShotRepository; import com.ctrip.apollo.biz.repository.ReleaseSnapShotRepository;
...@@ -7,7 +9,7 @@ import com.ctrip.apollo.biz.repository.VersionRepository; ...@@ -7,7 +9,7 @@ import com.ctrip.apollo.biz.repository.VersionRepository;
import com.ctrip.apollo.core.dto.ApolloConfig; import com.ctrip.apollo.core.dto.ApolloConfig;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
...@@ -21,7 +23,11 @@ import java.util.Map; ...@@ -21,7 +23,11 @@ import java.util.Map;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.anyObject;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/** /**
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
...@@ -40,7 +46,8 @@ public class ConfigServiceImplTest { ...@@ -40,7 +46,8 @@ public class ConfigServiceImplTest {
public void setUp() throws Exception { public void setUp() throws Exception {
configService = new ConfigServiceImpl(); configService = new ConfigServiceImpl();
ReflectionTestUtils.setField(configService, "versionRepository", versionRepository); ReflectionTestUtils.setField(configService, "versionRepository", versionRepository);
ReflectionTestUtils.setField(configService, "releaseSnapShotRepository", releaseSnapShotRepository); ReflectionTestUtils
.setField(configService, "releaseSnapShotRepository", releaseSnapShotRepository);
ReflectionTestUtils.setField(configService, "objectMapper", objectMapper); ReflectionTestUtils.setField(configService, "objectMapper", objectMapper);
} }
...@@ -53,12 +60,16 @@ public class ConfigServiceImplTest { ...@@ -53,12 +60,16 @@ public class ConfigServiceImplTest {
String someValidConfiguration = "{\"apollo.bar\": \"foo\"}"; String someValidConfiguration = "{\"apollo.bar\": \"foo\"}";
Version someVersion = assembleVersion(someAppId, someVersionName, someReleaseId); Version someVersion = assembleVersion(someAppId, someVersionName, someReleaseId);
ReleaseSnapShot someReleaseSnapShot = assembleReleaseSnapShot(someReleaseId, someClusterName, someValidConfiguration); ReleaseSnapShot
someReleaseSnapShot =
assembleReleaseSnapShot(someReleaseId, someClusterName, someValidConfiguration);
Map<String, Object> someMap = Maps.newHashMap(); Map<String, Object> someMap = Maps.newHashMap();
when(versionRepository.findByAppIdAndName(someAppId, someVersionName)).thenReturn(someVersion); when(versionRepository.findByAppIdAndName(someAppId, someVersionName)).thenReturn(someVersion);
when(releaseSnapShotRepository.findByReleaseIdAndClusterName(someReleaseId, someClusterName)).thenReturn(someReleaseSnapShot); when(releaseSnapShotRepository.findByReleaseIdAndClusterName(someReleaseId, someClusterName))
when(objectMapper.readValue(eq(someValidConfiguration), (TypeReference) anyObject())).thenReturn(someMap); .thenReturn(someReleaseSnapShot);
when(objectMapper.readValue(eq(someValidConfiguration), (TypeReference) anyObject()))
.thenReturn(someMap);
ApolloConfig result = configService.loadConfig(someAppId, someClusterName, someVersionName); ApolloConfig result = configService.loadConfig(someAppId, someClusterName, someVersionName);
...@@ -92,13 +103,15 @@ public class ConfigServiceImplTest { ...@@ -92,13 +103,15 @@ public class ConfigServiceImplTest {
Version someVersion = assembleVersion(someAppId, someVersionName, someReleaseId); Version someVersion = assembleVersion(someAppId, someVersionName, someReleaseId);
when(versionRepository.findByAppIdAndName(someAppId, someVersionName)).thenReturn(someVersion); when(versionRepository.findByAppIdAndName(someAppId, someVersionName)).thenReturn(someVersion);
when(releaseSnapShotRepository.findByReleaseIdAndClusterName(someReleaseId, someClusterName)).thenReturn(null); when(releaseSnapShotRepository.findByReleaseIdAndClusterName(someReleaseId, someClusterName))
.thenReturn(null);
ApolloConfig result = configService.loadConfig(someAppId, someClusterName, someVersionName); ApolloConfig result = configService.loadConfig(someAppId, someClusterName, someVersionName);
assertNull(result); assertNull(result);
verify(versionRepository, times(1)).findByAppIdAndName(someAppId, someVersionName); verify(versionRepository, times(1)).findByAppIdAndName(someAppId, someVersionName);
verify(releaseSnapShotRepository, times(1)).findByReleaseIdAndClusterName(someReleaseId, someClusterName); verify(releaseSnapShotRepository, times(1))
.findByReleaseIdAndClusterName(someReleaseId, someClusterName);
} }
private Version assembleVersion(long appId, String versionName, long releaseId) { private Version assembleVersion(long appId, String versionName, long releaseId) {
...@@ -109,7 +122,8 @@ public class ConfigServiceImplTest { ...@@ -109,7 +122,8 @@ public class ConfigServiceImplTest {
return version; return version;
} }
private ReleaseSnapShot assembleReleaseSnapShot(long releaseId, String clusterName, String configurations) { private ReleaseSnapShot assembleReleaseSnapShot(long releaseId, String clusterName,
String configurations) {
ReleaseSnapShot releaseSnapShot = new ReleaseSnapShot(); ReleaseSnapShot releaseSnapShot = new ReleaseSnapShot();
releaseSnapShot.setReleaseId(releaseId); releaseSnapShot.setReleaseId(releaseId);
releaseSnapShot.setClusterName(clusterName); releaseSnapShot.setClusterName(clusterName);
...@@ -122,20 +136,25 @@ public class ConfigServiceImplTest { ...@@ -122,20 +136,25 @@ public class ConfigServiceImplTest {
public void testTransformConfigurationToMapSuccessful() throws Exception { public void testTransformConfigurationToMapSuccessful() throws Exception {
String someValidConfiguration = "{\"apollo.bar\": \"foo\"}"; String someValidConfiguration = "{\"apollo.bar\": \"foo\"}";
Map<String, String> someMap = Maps.newHashMap(); Map<String, String> someMap = Maps.newHashMap();
when(objectMapper.readValue(eq(someValidConfiguration), (TypeReference) anyObject())).thenReturn(someMap); when(objectMapper.readValue(eq(someValidConfiguration), (TypeReference) anyObject()))
.thenReturn(someMap);
Map<String, Object> result = configService.transformConfigurationToMap(someValidConfiguration); Map<String, Object> result = configService.transformConfigurationToMap(someValidConfiguration);
assertEquals(someMap, result); assertEquals(someMap, result);
verify(objectMapper, times(1)).readValue(eq(someValidConfiguration), (TypeReference) anyObject()); verify(objectMapper, times(1))
.readValue(eq(someValidConfiguration), (TypeReference) anyObject());
} }
@Test @Test
public void testTransformConfigurationToMapFailed() throws Exception { public void testTransformConfigurationToMapFailed() throws Exception {
String someInvalidConfiguration = "xxx"; String someInvalidConfiguration = "xxx";
when(objectMapper.readValue(eq(someInvalidConfiguration), (TypeReference) anyObject())).thenThrow(IOException.class); when(objectMapper.readValue(eq(someInvalidConfiguration), (TypeReference) anyObject()))
.thenThrow(IOException.class);
Map<String, Object> result = configService.transformConfigurationToMap(someInvalidConfiguration); Map<String, Object>
result =
configService.transformConfigurationToMap(someInvalidConfiguration);
assertTrue(result.isEmpty()); assertTrue(result.isEmpty());
......
...@@ -5,6 +5,7 @@ import com.ctrip.apollo.client.loader.ConfigLoaderManager; ...@@ -5,6 +5,7 @@ import com.ctrip.apollo.client.loader.ConfigLoaderManager;
import com.ctrip.apollo.client.model.PropertyChange; import com.ctrip.apollo.client.model.PropertyChange;
import com.ctrip.apollo.client.model.PropertySourceReloadResult; import com.ctrip.apollo.client.model.PropertySourceReloadResult;
import com.ctrip.apollo.client.util.ConfigUtil; import com.ctrip.apollo.client.util.ConfigUtil;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
...@@ -35,9 +36,12 @@ import java.util.concurrent.atomic.AtomicReference; ...@@ -35,9 +36,12 @@ import java.util.concurrent.atomic.AtomicReference;
* *
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
*/ */
public class ApolloConfigManager implements BeanDefinitionRegistryPostProcessor, PriorityOrdered, ApplicationContextAware { public class ApolloConfigManager
implements BeanDefinitionRegistryPostProcessor, PriorityOrdered, ApplicationContextAware {
private static final Logger logger = LoggerFactory.getLogger(ApolloConfigManager.class); private static final Logger logger = LoggerFactory.getLogger(ApolloConfigManager.class);
private static AtomicReference<ApolloConfigManager> singletonProtector = new AtomicReference<ApolloConfigManager>(); private static AtomicReference<ApolloConfigManager>
singletonProtector =
new AtomicReference<ApolloConfigManager>();
private ConfigLoaderManager configLoaderManager; private ConfigLoaderManager configLoaderManager;
private ConfigurableApplicationContext applicationContext; private ConfigurableApplicationContext applicationContext;
...@@ -47,7 +51,7 @@ public class ApolloConfigManager implements BeanDefinitionRegistryPostProcessor, ...@@ -47,7 +51,7 @@ public class ApolloConfigManager implements BeanDefinitionRegistryPostProcessor,
private RefreshScope scope; private RefreshScope scope;
public ApolloConfigManager() { public ApolloConfigManager() {
if(!singletonProtector.compareAndSet(null, this)) { if (!singletonProtector.compareAndSet(null, this)) {
throw new IllegalStateException("There should be only one ApolloConfigManager instance!"); throw new IllegalStateException("There should be only one ApolloConfigManager instance!");
} }
this.configLoaderManager = ConfigLoaderFactory.getInstance().getConfigLoaderManager(); this.configLoaderManager = ConfigLoaderFactory.getInstance().getConfigLoaderManager();
...@@ -55,8 +59,8 @@ public class ApolloConfigManager implements BeanDefinitionRegistryPostProcessor, ...@@ -55,8 +59,8 @@ public class ApolloConfigManager implements BeanDefinitionRegistryPostProcessor,
this.counter = new AtomicLong(); this.counter = new AtomicLong();
executorService = Executors.newScheduledThreadPool(1, new ThreadFactory() { executorService = Executors.newScheduledThreadPool(1, new ThreadFactory() {
@Override @Override
public Thread newThread(Runnable r) { public Thread newThread(Runnable runnable) {
Thread thread = new Thread(r, "ApolloConfigManager-" + counter.incrementAndGet()); Thread thread = new Thread(runnable, "ApolloConfigManager-" + counter.incrementAndGet());
return thread; return thread;
} }
}); });
...@@ -66,7 +70,9 @@ public class ApolloConfigManager implements BeanDefinitionRegistryPostProcessor, ...@@ -66,7 +70,9 @@ public class ApolloConfigManager implements BeanDefinitionRegistryPostProcessor,
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (!(applicationContext instanceof ConfigurableApplicationContext)) { if (!(applicationContext instanceof ConfigurableApplicationContext)) {
throw new RuntimeException( throw new RuntimeException(
String.format("ApplicationContext must implement ConfigurableApplicationContext, but found: %s", applicationContext.getClass().getName())); String.format(
"ApplicationContext must implement ConfigurableApplicationContext, but found: %s",
applicationContext.getClass().getName()));
} }
this.applicationContext = (ConfigurableApplicationContext) applicationContext; this.applicationContext = (ConfigurableApplicationContext) applicationContext;
this.configUtil.setApplicationContext(applicationContext); this.configUtil.setApplicationContext(applicationContext);
...@@ -78,7 +84,8 @@ public class ApolloConfigManager implements BeanDefinitionRegistryPostProcessor, ...@@ -78,7 +84,8 @@ public class ApolloConfigManager implements BeanDefinitionRegistryPostProcessor,
* so that configurations could be injected correctly * so that configurations could be injected correctly
*/ */
@Override @Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
throws BeansException {
registerDependentBeans(registry); registerDependentBeans(registry);
initializePropertySource(); initializePropertySource();
schedulePeriodicRefresh(); schedulePeriodicRefresh();
...@@ -92,25 +99,30 @@ public class ApolloConfigManager implements BeanDefinitionRegistryPostProcessor, ...@@ -92,25 +99,30 @@ public class ApolloConfigManager implements BeanDefinitionRegistryPostProcessor,
* <li> * <li>
* - PropertySourcesPlaceholderConfigurer: used to support placeholder configuration injection * - PropertySourcesPlaceholderConfigurer: used to support placeholder configuration injection
* </li> * </li>
* @param registry
*/ */
private void registerDependentBeans(BeanDefinitionRegistry registry) { private void registerDependentBeans(BeanDefinitionRegistry registry) {
BeanDefinition refreshScope = BeanDefinitionBuilder.genericBeanDefinition(RefreshScope.class).getBeanDefinition(); BeanDefinition
refreshScope =
BeanDefinitionBuilder.genericBeanDefinition(RefreshScope.class).getBeanDefinition();
registry.registerBeanDefinition("refreshScope", refreshScope); registry.registerBeanDefinition("refreshScope", refreshScope);
BeanDefinition propertySourcesPlaceholderConfigurer = BeanDefinitionBuilder.genericBeanDefinition(PropertySourcesPlaceholderConfigurer.class).getBeanDefinition(); BeanDefinition
registry.registerBeanDefinition("propertySourcesPlaceholderConfigurer", propertySourcesPlaceholderConfigurer); propertySourcesPlaceholderConfigurer =
BeanDefinitionBuilder.genericBeanDefinition(PropertySourcesPlaceholderConfigurer.class)
.getBeanDefinition();
registry.registerBeanDefinition("propertySourcesPlaceholderConfigurer",
propertySourcesPlaceholderConfigurer);
} }
/** /**
* This is executed after postProcessBeanDefinitionRegistry * This is executed after postProcessBeanDefinitionRegistry
*/ */
@Override @Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
} }
/** /**
* Make sure this bean is called before other beans * Make sure this bean is called before other beans
* @return
*/ */
@Override @Override
public int getOrder() { public int getOrder() {
...@@ -128,7 +140,9 @@ public class ApolloConfigManager implements BeanDefinitionRegistryPostProcessor, ...@@ -128,7 +140,9 @@ public class ApolloConfigManager implements BeanDefinitionRegistryPostProcessor,
} }
private void updateEnvironmentPropertySource(CompositePropertySource currentPropertySource) { private void updateEnvironmentPropertySource(CompositePropertySource currentPropertySource) {
MutablePropertySources currentPropertySources = applicationContext.getEnvironment().getPropertySources(); MutablePropertySources
currentPropertySources =
applicationContext.getEnvironment().getPropertySources();
if (currentPropertySources.contains(currentPropertySource.getName())) { if (currentPropertySources.contains(currentPropertySource.getName())) {
currentPropertySources.replace(currentPropertySource.getName(), currentPropertySource); currentPropertySources.replace(currentPropertySource.getName(), currentPropertySource);
return; return;
...@@ -137,16 +151,18 @@ public class ApolloConfigManager implements BeanDefinitionRegistryPostProcessor, ...@@ -137,16 +151,18 @@ public class ApolloConfigManager implements BeanDefinitionRegistryPostProcessor,
} }
void schedulePeriodicRefresh() { void schedulePeriodicRefresh() {
executorService.scheduleAtFixedRate(new Runnable() { executorService.scheduleAtFixedRate(
new Runnable() {
@Override @Override
public void run() { public void run() {
try { try {
updatePropertySource(); updatePropertySource();
} catch (Throwable e) { } catch (Throwable ex) {
logger.error("Refreshing config failed", e); logger.error("Refreshing config failed", ex);
} }
} }
}, configUtil.getRefreshInterval(), configUtil.getRefreshInterval(), configUtil.getRefreshTimeUnit()); }, configUtil.getRefreshInterval(), configUtil.getRefreshInterval(),
configUtil.getRefreshTimeUnit());
} }
public List<PropertyChange> updatePropertySource() { public List<PropertyChange> updatePropertySource() {
......
package com.ctrip.apollo.client.env; package com.ctrip.apollo.client.env;
import com.ctrip.apollo.Apollo;
import com.ctrip.apollo.Apollo.Env;
import com.ctrip.apollo.client.constants.Constants;
import com.ctrip.apollo.core.MetaDomainConsts;
import com.ctrip.apollo.core.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
...@@ -10,20 +19,11 @@ import java.util.Enumeration; ...@@ -10,20 +19,11 @@ import java.util.Enumeration;
import java.util.Properties; import java.util.Properties;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ctrip.apollo.Apollo;
import com.ctrip.apollo.Apollo.Env;
import com.ctrip.apollo.client.constants.Constants;
import com.ctrip.apollo.core.MetaDomainConsts;
import com.ctrip.apollo.core.utils.StringUtils;
public class ClientEnvironment { public class ClientEnvironment {
private static final Logger logger = LoggerFactory.getLogger(ClientEnvironment.class); private static final Logger logger = LoggerFactory.getLogger(ClientEnvironment.class);
private final static String DEFAULT_FILE = "/apollo.properties"; private static final String DEFAULT_FILE = "/apollo.properties";
private AtomicReference<Env> env = new AtomicReference<Env>(); private AtomicReference<Env> env = new AtomicReference<Env>();
...@@ -84,20 +84,20 @@ public class ClientEnvironment { ...@@ -84,20 +84,20 @@ public class ClientEnvironment {
props.load(in); props.load(in);
in.close(); in.close();
} }
} catch (Exception e) { } catch (Exception ex) {
logger.warn("Reading config failed: {}", e.getMessage()); logger.warn("Reading config failed: {}", ex.getMessage());
} finally { } finally {
if (in != null) { if (in != null) {
try { try {
in.close(); in.close();
} catch (IOException e) { } catch (IOException ex) {
logger.warn("Close config failed: {}", e.getMessage()); logger.warn("Close config failed: {}", ex.getMessage());
} }
} }
} }
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (Enumeration<String> e = (Enumeration<String>) props.propertyNames(); e for (Enumeration<String> e = (Enumeration<String>) props.propertyNames(); e
.hasMoreElements();) { .hasMoreElements(); ) {
String key = e.nextElement(); String key = e.nextElement();
String val = (String) props.getProperty(key); String val = (String) props.getProperty(key);
sb.append(key).append('=').append(val).append('\n'); sb.append(key).append('=').append(val).append('\n');
......
package com.ctrip.apollo.client.loader; package com.ctrip.apollo.client.loader;
import com.ctrip.apollo.client.loader.impl.InMemoryConfigLoader;
import com.ctrip.apollo.client.loader.impl.LocalFileConfigLoader;
import com.ctrip.apollo.Apollo.Env; import com.ctrip.apollo.Apollo.Env;
import com.ctrip.apollo.client.env.ClientEnvironment; import com.ctrip.apollo.client.env.ClientEnvironment;
import com.ctrip.apollo.client.loader.impl.InMemoryConfigLoader;
import com.ctrip.apollo.client.loader.impl.LocalFileConfigLoader;
import com.ctrip.apollo.client.loader.impl.RemoteConfigLoader; import com.ctrip.apollo.client.loader.impl.RemoteConfigLoader;
import com.ctrip.apollo.client.util.ConfigUtil; import com.ctrip.apollo.client.util.ConfigUtil;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
/** /**
...@@ -14,7 +15,8 @@ import org.springframework.web.client.RestTemplate; ...@@ -14,7 +15,8 @@ import org.springframework.web.client.RestTemplate;
public class ConfigLoaderFactory { public class ConfigLoaderFactory {
private static ConfigLoaderFactory configLoaderFactory = new ConfigLoaderFactory(); private static ConfigLoaderFactory configLoaderFactory = new ConfigLoaderFactory();
private ConfigLoaderFactory() {} private ConfigLoaderFactory() {
}
public static ConfigLoaderFactory getInstance() { public static ConfigLoaderFactory getInstance() {
return configLoaderFactory; return configLoaderFactory;
...@@ -32,7 +34,10 @@ public class ConfigLoaderFactory { ...@@ -32,7 +34,10 @@ public class ConfigLoaderFactory {
} }
public ConfigLoader getRemoteConfigLoader() { public ConfigLoader getRemoteConfigLoader() {
ConfigLoader remoteConfigLoader = new RemoteConfigLoader(new RestTemplate(), ConfigUtil.getInstance(), new ConfigServiceLocator()); ConfigLoader
remoteConfigLoader =
new RemoteConfigLoader(new RestTemplate(), ConfigUtil.getInstance(),
new ConfigServiceLocator());
// remoteConfigLoader.setFallBackLoader(getInMemoryConfigLoader()); // remoteConfigLoader.setFallBackLoader(getInMemoryConfigLoader());
return remoteConfigLoader; return remoteConfigLoader;
} }
......
package com.ctrip.apollo.client.loader; package com.ctrip.apollo.client.loader;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.ctrip.apollo.client.enums.PropertyChangeType; import com.ctrip.apollo.client.enums.PropertyChangeType;
import com.ctrip.apollo.client.model.ApolloRegistry; import com.ctrip.apollo.client.model.ApolloRegistry;
import com.ctrip.apollo.client.model.PropertyChange; import com.ctrip.apollo.client.model.PropertyChange;
import com.ctrip.apollo.client.model.PropertySourceReloadResult; import com.ctrip.apollo.client.model.PropertySourceReloadResult;
import com.ctrip.apollo.client.util.ConfigUtil; import com.ctrip.apollo.client.util.ConfigUtil;
import com.ctrip.apollo.core.dto.ApolloConfig; import com.ctrip.apollo.core.dto.ApolloConfig;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.CompositePropertySource;
...@@ -19,7 +21,12 @@ import java.util.Collections; ...@@ -19,7 +21,12 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.*; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
/** /**
...@@ -42,8 +49,8 @@ public class ConfigLoaderManager { ...@@ -42,8 +49,8 @@ public class ConfigLoaderManager {
this.counter = new AtomicLong(); this.counter = new AtomicLong();
this.executorService = Executors.newFixedThreadPool(5, new ThreadFactory() { this.executorService = Executors.newFixedThreadPool(5, new ThreadFactory() {
@Override @Override
public Thread newThread(Runnable r) { public Thread newThread(Runnable runnable) {
Thread thread = new Thread(r, "ConfigLoaderManager-" + counter.incrementAndGet()); Thread thread = new Thread(runnable, "ConfigLoaderManager-" + counter.incrementAndGet());
return thread; return thread;
} }
}); });
...@@ -53,8 +60,8 @@ public class ConfigLoaderManager { ...@@ -53,8 +60,8 @@ public class ConfigLoaderManager {
public CompositePropertySource loadPropertySource() { public CompositePropertySource loadPropertySource() {
try { try {
apolloRegistries = configUtil.loadApolloRegistries(); apolloRegistries = configUtil.loadApolloRegistries();
} catch (IOException e) { } catch (IOException ex) {
throw new RuntimeException("Load apollo config registry failed", e); throw new RuntimeException("Load apollo config registry failed", ex);
} }
return loadPropertySourceWithApolloRegistries(apolloRegistries); return loadPropertySourceWithApolloRegistries(apolloRegistries);
...@@ -62,7 +69,9 @@ public class ConfigLoaderManager { ...@@ -62,7 +69,9 @@ public class ConfigLoaderManager {
public PropertySourceReloadResult reloadPropertySource() { public PropertySourceReloadResult reloadPropertySource() {
CompositePropertySource composite = loadPropertySourceWithApolloRegistries(apolloRegistries); CompositePropertySource composite = loadPropertySourceWithApolloRegistries(apolloRegistries);
List<ApolloConfig> previous = Lists.newArrayList(this.previousApolloRegistryConfigCache.values()); List<ApolloConfig>
previous =
Lists.newArrayList(this.previousApolloRegistryConfigCache.values());
List<ApolloConfig> current = Lists.newArrayList(this.currentApolloRegistryConfigCache.values()); List<ApolloConfig> current = Lists.newArrayList(this.currentApolloRegistryConfigCache.values());
return new PropertySourceReloadResult(composite, calcPropertyChanges(previous, current)); return new PropertySourceReloadResult(composite, calcPropertyChanges(previous, current));
} }
...@@ -71,10 +80,9 @@ public class ConfigLoaderManager { ...@@ -71,10 +80,9 @@ public class ConfigLoaderManager {
* Load property source with apollo registries provided * Load property source with apollo registries provided
* Should not be invoked in parallel since there are some operations like create/destroy cache, * Should not be invoked in parallel since there are some operations like create/destroy cache,
* writing to files etc. * writing to files etc.
* @param apolloRegistries
* @return
*/ */
private synchronized CompositePropertySource loadPropertySourceWithApolloRegistries(List<ApolloRegistry> apolloRegistries) { private synchronized CompositePropertySource loadPropertySourceWithApolloRegistries(
List<ApolloRegistry> apolloRegistries) {
resetApolloRegistryConfigCache(); resetApolloRegistryConfigCache();
CompositePropertySource composite = new CompositePropertySource(APOLLO_PROPERTY_SOURCE_NAME); CompositePropertySource composite = new CompositePropertySource(APOLLO_PROPERTY_SOURCE_NAME);
if (apolloRegistries == null || apolloRegistries.isEmpty()) { if (apolloRegistries == null || apolloRegistries.isEmpty()) {
...@@ -86,7 +94,8 @@ public class ConfigLoaderManager { ...@@ -86,7 +94,8 @@ public class ConfigLoaderManager {
Collections.sort(apolloConfigList); Collections.sort(apolloConfigList);
for (ApolloConfig apolloConfig : apolloConfigList) { for (ApolloConfig apolloConfig : apolloConfigList) {
composite.addPropertySource(new MapPropertySource(assemblePropertySourceName(apolloConfig), apolloConfig.getConfigurations())); composite.addPropertySource(new MapPropertySource(assemblePropertySourceName(apolloConfig),
apolloConfig.getConfigurations()));
} }
return composite; return composite;
} catch (Throwable throwable) { } catch (Throwable throwable) {
...@@ -94,7 +103,8 @@ public class ConfigLoaderManager { ...@@ -94,7 +103,8 @@ public class ConfigLoaderManager {
} }
} }
List<PropertyChange> calcPropertyChanges(List<ApolloConfig> previous, List<ApolloConfig> current) { List<PropertyChange> calcPropertyChanges(List<ApolloConfig> previous,
List<ApolloConfig> current) {
Map<String, Object> previousMap = collectConfigurations(previous); Map<String, Object> previousMap = collectConfigurations(previous);
Map<String, Object> currentMap = collectConfigurations(current); Map<String, Object> currentMap = collectConfigurations(current);
...@@ -112,14 +122,17 @@ public class ConfigLoaderManager { ...@@ -112,14 +122,17 @@ public class ConfigLoaderManager {
} }
for (String removedKey : removedKeys) { for (String removedKey : removedKeys) {
changes.add(new PropertyChange(removedKey, previousMap.get(removedKey), null, PropertyChangeType.DELETED)); changes.add(new PropertyChange(removedKey, previousMap.get(removedKey), null,
PropertyChangeType.DELETED));
} }
for (String commonKey : commonKeys) { for (String commonKey : commonKeys) {
if (previousMap.get(commonKey).equals(currentMap.get(commonKey))) { if (previousMap.get(commonKey).equals(currentMap.get(commonKey))) {
continue; continue;
} }
changes.add(new PropertyChange(commonKey, previousMap.get(commonKey), currentMap.get(commonKey), PropertyChangeType.MODIFIED)); changes.add(
new PropertyChange(commonKey, previousMap.get(commonKey), currentMap.get(commonKey),
PropertyChangeType.MODIFIED));
} }
return changes; return changes;
...@@ -152,15 +165,17 @@ public class ConfigLoaderManager { ...@@ -152,15 +165,17 @@ public class ConfigLoaderManager {
continue; continue;
} }
apolloConfigList.add(result); apolloConfigList.add(result);
} catch (ExecutionException e) { } catch (ExecutionException ex) {
throw e.getCause(); throw ex.getCause();
} }
} }
return apolloConfigList; return apolloConfigList;
} }
ApolloConfig loadSingleApolloConfig(ApolloRegistry apolloRegistry) { ApolloConfig loadSingleApolloConfig(ApolloRegistry apolloRegistry) {
ApolloConfig result = configLoader.loadApolloConfig(apolloRegistry, getPreviousApolloConfig(apolloRegistry)); ApolloConfig
result =
configLoader.loadApolloConfig(apolloRegistry, getPreviousApolloConfig(apolloRegistry));
if (result == null) { if (result == null) {
logger.error("Loaded config null..."); logger.error("Loaded config null...");
return null; return null;
...@@ -185,6 +200,7 @@ public class ConfigLoaderManager { ...@@ -185,6 +200,7 @@ public class ConfigLoaderManager {
} }
private String assemblePropertySourceName(ApolloConfig apolloConfig) { private String assemblePropertySourceName(ApolloConfig apolloConfig) {
return String.format("%d-%s-%s-%d", apolloConfig.getAppId(), apolloConfig.getCluster(), apolloConfig.getVersion(), apolloConfig.getReleaseId()); return String.format("%d-%s-%s-%d", apolloConfig.getAppId(), apolloConfig.getCluster(),
apolloConfig.getVersion(), apolloConfig.getReleaseId());
} }
} }
package com.ctrip.apollo.client.loader; package com.ctrip.apollo.client.loader;
import java.net.URI; import com.ctrip.apollo.client.env.ClientEnvironment;
import java.util.ArrayList; import com.ctrip.apollo.core.serivce.ApolloService;
import java.util.List;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import com.ctrip.apollo.client.env.ClientEnvironment; import java.net.URI;
import com.ctrip.apollo.core.serivce.ApolloService; import java.util.ArrayList;
import java.util.List;
public class ConfigServiceLocator { public class ConfigServiceLocator {
...@@ -31,8 +31,8 @@ public class ConfigServiceLocator { ...@@ -31,8 +31,8 @@ public class ConfigServiceLocator {
serviceCaches.add(service); serviceCaches.add(service);
} }
} }
} catch (Exception e) { } catch (Exception ex) {
logger.warn(e.getMessage()); logger.warn(ex.getMessage());
} }
return serviceCaches; return serviceCaches;
} }
......
...@@ -3,6 +3,7 @@ package com.ctrip.apollo.client.loader.impl; ...@@ -3,6 +3,7 @@ package com.ctrip.apollo.client.loader.impl;
import com.ctrip.apollo.client.loader.ConfigLoader; import com.ctrip.apollo.client.loader.ConfigLoader;
import com.ctrip.apollo.client.model.ApolloRegistry; import com.ctrip.apollo.client.model.ApolloRegistry;
import com.ctrip.apollo.core.dto.ApolloConfig; import com.ctrip.apollo.core.dto.ApolloConfig;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -17,16 +18,19 @@ public abstract class AbstractConfigLoader implements ConfigLoader { ...@@ -17,16 +18,19 @@ public abstract class AbstractConfigLoader implements ConfigLoader {
public ApolloConfig loadApolloConfig(ApolloRegistry apolloRegistry, ApolloConfig previous) { public ApolloConfig loadApolloConfig(ApolloRegistry apolloRegistry, ApolloConfig previous) {
try { try {
return doLoadApolloConfig(apolloRegistry, previous); return doLoadApolloConfig(apolloRegistry, previous);
} catch (Throwable e) { } catch (Throwable ex) {
if (this.fallback == null) { if (this.fallback == null) {
throw new RuntimeException(String.format("Load Apollo Config failed - %s", apolloRegistry.toString()), e); throw new RuntimeException(
String.format("Load Apollo Config failed - %s", apolloRegistry.toString()), ex);
} }
logger.error("Load Config via {} failed, try to use its fallback {} to load", getClass().getSimpleName(), fallback.getClass().getSimpleName(), e); logger.error("Load Config via {} failed, try to use its fallback {} to load",
getClass().getSimpleName(), fallback.getClass().getSimpleName(), ex);
return this.fallback.loadApolloConfig(apolloRegistry, previous); return this.fallback.loadApolloConfig(apolloRegistry, previous);
} }
} }
protected abstract ApolloConfig doLoadApolloConfig(ApolloRegistry apolloRegistry, ApolloConfig previous); protected abstract ApolloConfig doLoadApolloConfig(ApolloRegistry apolloRegistry,
ApolloConfig previous);
@Override @Override
public void setFallBackLoader(ConfigLoader configLoader) { public void setFallBackLoader(ConfigLoader configLoader) {
......
...@@ -6,7 +6,7 @@ import com.ctrip.apollo.core.dto.ApolloConfig; ...@@ -6,7 +6,7 @@ import com.ctrip.apollo.core.dto.ApolloConfig;
/** /**
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
*/ */
public class InMemoryConfigLoader extends AbstractConfigLoader{ public class InMemoryConfigLoader extends AbstractConfigLoader {
@Override @Override
protected ApolloConfig doLoadApolloConfig(ApolloRegistry apolloRegistry, ApolloConfig previous) { protected ApolloConfig doLoadApolloConfig(ApolloRegistry apolloRegistry, ApolloConfig previous) {
......
...@@ -5,9 +5,10 @@ import com.ctrip.apollo.core.dto.ApolloConfig; ...@@ -5,9 +5,10 @@ import com.ctrip.apollo.core.dto.ApolloConfig;
/** /**
* Load config from local backup file * Load config from local backup file
*
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
*/ */
public class LocalFileConfigLoader extends AbstractConfigLoader{ public class LocalFileConfigLoader extends AbstractConfigLoader {
@Override @Override
public ApolloConfig doLoadApolloConfig(ApolloRegistry apolloRegistry, ApolloConfig previous) { public ApolloConfig doLoadApolloConfig(ApolloRegistry apolloRegistry, ApolloConfig previous) {
return null; return null;
......
package com.ctrip.apollo.client.loader.impl; package com.ctrip.apollo.client.loader.impl;
import com.google.common.collect.Maps;
import com.ctrip.apollo.client.loader.ConfigServiceLocator; import com.ctrip.apollo.client.loader.ConfigServiceLocator;
import com.ctrip.apollo.client.model.ApolloRegistry; import com.ctrip.apollo.client.model.ApolloRegistry;
import com.ctrip.apollo.client.util.ConfigUtil; import com.ctrip.apollo.client.util.ConfigUtil;
import com.ctrip.apollo.core.dto.ApolloConfig; import com.ctrip.apollo.core.dto.ApolloConfig;
import com.ctrip.apollo.core.serivce.ApolloService; import com.ctrip.apollo.core.serivce.ApolloService;
import com.google.common.collect.Maps;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity; import org.springframework.http.HttpEntity;
...@@ -29,17 +31,20 @@ public class RemoteConfigLoader extends AbstractConfigLoader { ...@@ -29,17 +31,20 @@ public class RemoteConfigLoader extends AbstractConfigLoader {
private final ConfigUtil configUtil; private final ConfigUtil configUtil;
private final ConfigServiceLocator serviceLocator; private final ConfigServiceLocator serviceLocator;
public RemoteConfigLoader(RestTemplate restTemplate, ConfigUtil configUtil, ConfigServiceLocator locator) { public RemoteConfigLoader(RestTemplate restTemplate, ConfigUtil configUtil,
ConfigServiceLocator locator) {
this.restTemplate = restTemplate; this.restTemplate = restTemplate;
this.configUtil = configUtil; this.configUtil = configUtil;
this.serviceLocator = locator; this.serviceLocator = locator;
} }
ApolloConfig getRemoteConfig(RestTemplate restTemplate, String uri, String cluster, ApolloRegistry apolloRegistry, ApolloConfig previousConfig) { ApolloConfig getRemoteConfig(RestTemplate restTemplate, String uri, String cluster,
ApolloRegistry apolloRegistry, ApolloConfig previousConfig) {
long appId = apolloRegistry.getAppId(); long appId = apolloRegistry.getAppId();
String version = apolloRegistry.getVersion(); String version = apolloRegistry.getVersion();
logger.info("Loading config from {}, appId={}, cluster={}, version={}", uri, appId, cluster, version); logger.info("Loading config from {}, appId={}, cluster={}, version={}", uri, appId, cluster,
version);
String path = "/config/{appId}/{cluster}"; String path = "/config/{appId}/{cluster}";
Map<String, Object> paramMap = Maps.newHashMap(); Map<String, Object> paramMap = Maps.newHashMap();
paramMap.put("appId", appId); paramMap.put("appId", appId);
...@@ -60,8 +65,8 @@ public class RemoteConfigLoader extends AbstractConfigLoader { ...@@ -60,8 +65,8 @@ public class RemoteConfigLoader extends AbstractConfigLoader {
// TODO retry // TODO retry
response = restTemplate.exchange(uri response = restTemplate.exchange(uri
+ path, HttpMethod.GET, new HttpEntity<Void>((Void) null), ApolloConfig.class, paramMap); + path, HttpMethod.GET, new HttpEntity<Void>((Void) null), ApolloConfig.class, paramMap);
} catch (Throwable e) { } catch (Throwable ex) {
throw e; throw ex;
} }
if (response == null) { if (response == null) {
...@@ -73,7 +78,8 @@ public class RemoteConfigLoader extends AbstractConfigLoader { ...@@ -73,7 +78,8 @@ public class RemoteConfigLoader extends AbstractConfigLoader {
} }
if (response.getStatusCode() != HttpStatus.OK) { if (response.getStatusCode() != HttpStatus.OK) {
throw new RuntimeException(String.format("Load apollo config failed, response status %s", response.getStatusCode())); throw new RuntimeException(
String.format("Load apollo config failed, response status %s", response.getStatusCode()));
} }
ApolloConfig result = response.getBody(); ApolloConfig result = response.getBody();
...@@ -91,7 +97,7 @@ public class RemoteConfigLoader extends AbstractConfigLoader { ...@@ -91,7 +97,7 @@ public class RemoteConfigLoader extends AbstractConfigLoader {
private String getConfigServiceUrl() { private String getConfigServiceUrl() {
List<ApolloService> services = serviceLocator.getConfigServices(); List<ApolloService> services = serviceLocator.getConfigServices();
if(services.size()==0){ if (services.size() == 0) {
throw new RuntimeException("No available config service"); throw new RuntimeException("No available config service");
} }
return services.get(0).getHomepageUrl(); return services.get(0).getHomepageUrl();
......
...@@ -11,7 +11,8 @@ public class PropertyChange { ...@@ -11,7 +11,8 @@ public class PropertyChange {
private Object newValue; private Object newValue;
private PropertyChangeType changeType; private PropertyChangeType changeType;
public PropertyChange(String propertyName, Object oldValue, Object newValue, PropertyChangeType changeType) { public PropertyChange(String propertyName, Object oldValue, Object newValue,
PropertyChangeType changeType) {
this.propertyName = propertyName; this.propertyName = propertyName;
this.oldValue = oldValue; this.oldValue = oldValue;
this.newValue = newValue; this.newValue = newValue;
......
package com.ctrip.apollo.client.model; package com.ctrip.apollo.client.model;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.CompositePropertySource;
import java.util.List; import java.util.List;
...@@ -17,7 +18,8 @@ public class PropertySourceReloadResult { ...@@ -17,7 +18,8 @@ public class PropertySourceReloadResult {
changes = Lists.newArrayList(); changes = Lists.newArrayList();
} }
public PropertySourceReloadResult(CompositePropertySource propertySource, List<PropertyChange> changes) { public PropertySourceReloadResult(CompositePropertySource propertySource,
List<PropertyChange> changes) {
this.propertySource = propertySource; this.propertySource = propertySource;
this.changes = changes; this.changes = changes;
} }
......
package com.ctrip.apollo.client.util; package com.ctrip.apollo.client.util;
import com.ctrip.apollo.client.constants.Constants;
import com.ctrip.apollo.client.model.ApolloRegistry;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.collect.FluentIterable; import com.google.common.collect.FluentIterable;
import com.ctrip.apollo.client.constants.Constants;
import com.ctrip.apollo.client.model.ApolloRegistry;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.io.support.EncodedResource; import org.springframework.core.io.support.EncodedResource;
...@@ -66,7 +68,8 @@ public class ConfigUtil { ...@@ -66,7 +68,8 @@ public class ConfigUtil {
} }
ApolloRegistry registry = new ApolloRegistry(); ApolloRegistry registry = new ApolloRegistry();
registry.setAppId(Long.parseLong(properties.getProperty(Constants.APP_ID))); registry.setAppId(Long.parseLong(properties.getProperty(Constants.APP_ID)));
registry.setVersion(properties.getProperty(Constants.VERSION, Constants.DEFAULT_VERSION_NAME)); registry.setVersion(
properties.getProperty(Constants.VERSION, Constants.DEFAULT_VERSION_NAME));
return registry; return registry;
} }
}).filter(Predicates.notNull()).toList(); }).filter(Predicates.notNull()).toList();
...@@ -80,8 +83,8 @@ public class ConfigUtil { ...@@ -80,8 +83,8 @@ public class ConfigUtil {
} }
try { try {
return PropertiesLoaderUtils.loadProperties(new EncodedResource(resource, "UTF-8")); return PropertiesLoaderUtils.loadProperties(new EncodedResource(resource, "UTF-8"));
} catch (IOException e) { } catch (IOException ex) {
e.printStackTrace(); ex.printStackTrace();
} }
return null; return null;
} }
......
...@@ -3,14 +3,15 @@ package com.ctrip.apollo.client; ...@@ -3,14 +3,15 @@ package com.ctrip.apollo.client;
import com.ctrip.apollo.client.loader.ConfigLoaderManagerTest; import com.ctrip.apollo.client.loader.ConfigLoaderManagerTest;
import com.ctrip.apollo.client.loader.impl.RemoteConfigLoaderTest; import com.ctrip.apollo.client.loader.impl.RemoteConfigLoaderTest;
import com.ctrip.apollo.client.util.ConfigUtilTest; import com.ctrip.apollo.client.util.ConfigUtilTest;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.Suite; import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses; import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class) @RunWith(Suite.class)
@SuiteClasses({ @SuiteClasses({
ApolloConfigManagerTest.class, ConfigLoaderManagerTest.class, RemoteConfigLoaderTest.class, ApolloConfigManagerTest.class, ConfigLoaderManagerTest.class, RemoteConfigLoaderTest.class,
ConfigUtilTest.class ConfigUtilTest.class
}) })
public class AllTests { public class AllTests {
......
...@@ -3,6 +3,7 @@ package com.ctrip.apollo.client; ...@@ -3,6 +3,7 @@ package com.ctrip.apollo.client;
import com.ctrip.apollo.client.loader.ConfigLoaderManager; import com.ctrip.apollo.client.loader.ConfigLoaderManager;
import com.ctrip.apollo.client.model.PropertyChange; import com.ctrip.apollo.client.model.PropertyChange;
import com.ctrip.apollo.client.model.PropertySourceReloadResult; import com.ctrip.apollo.client.model.PropertySourceReloadResult;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
...@@ -25,7 +26,15 @@ import java.util.List; ...@@ -25,7 +26,15 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/** /**
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
...@@ -61,7 +70,8 @@ public class ApolloConfigManagerTest { ...@@ -61,7 +70,8 @@ public class ApolloConfigManagerTest {
@After @After
public void tearDown() throws Exception { public void tearDown() throws Exception {
AtomicReference<ApolloConfigManager> singletonProtector = AtomicReference<ApolloConfigManager> singletonProtector =
(AtomicReference<ApolloConfigManager>)ReflectionTestUtils.getField(ApolloConfigManager.class, "singletonProtector"); (AtomicReference<ApolloConfigManager>) ReflectionTestUtils
.getField(ApolloConfigManager.class, "singletonProtector");
singletonProtector.set(null); singletonProtector.set(null);
} }
...@@ -74,7 +84,9 @@ public class ApolloConfigManagerTest { ...@@ -74,7 +84,9 @@ public class ApolloConfigManagerTest {
@Test @Test
public void testInitializePropertySourceSuccessfully() { public void testInitializePropertySourceSuccessfully() {
CompositePropertySource somePropertySource = mock(CompositePropertySource.class); CompositePropertySource somePropertySource = mock(CompositePropertySource.class);
final ArgumentCaptor<CompositePropertySource> captor = ArgumentCaptor.forClass(CompositePropertySource.class); final ArgumentCaptor<CompositePropertySource>
captor =
ArgumentCaptor.forClass(CompositePropertySource.class);
when(configLoaderManager.loadPropertySource()).thenReturn(somePropertySource); when(configLoaderManager.loadPropertySource()).thenReturn(somePropertySource);
...@@ -94,12 +106,15 @@ public class ApolloConfigManagerTest { ...@@ -94,12 +106,15 @@ public class ApolloConfigManagerTest {
apolloConfigManager.postProcessBeanDefinitionRegistry(beanDefinitionRegistry); apolloConfigManager.postProcessBeanDefinitionRegistry(beanDefinitionRegistry);
verify(beanDefinitionRegistry, times(2)).registerBeanDefinition(anyString(), any(BeanDefinition.class)); verify(beanDefinitionRegistry, times(2))
.registerBeanDefinition(anyString(), any(BeanDefinition.class));
} }
@Test @Test
public void testUpdatePropertySourceWithChanges() throws Exception { public void testUpdatePropertySourceWithChanges() throws Exception {
PropertySourceReloadResult somePropertySourceReloadResult = mock(PropertySourceReloadResult.class); PropertySourceReloadResult
somePropertySourceReloadResult =
mock(PropertySourceReloadResult.class);
CompositePropertySource somePropertySource = mock(CompositePropertySource.class); CompositePropertySource somePropertySource = mock(CompositePropertySource.class);
List<PropertyChange> someChanges = mock(List.class); List<PropertyChange> someChanges = mock(List.class);
...@@ -116,7 +131,9 @@ public class ApolloConfigManagerTest { ...@@ -116,7 +131,9 @@ public class ApolloConfigManagerTest {
@Test @Test
public void testUpdatePropertySourceWithNoChange() throws Exception { public void testUpdatePropertySourceWithNoChange() throws Exception {
PropertySourceReloadResult somePropertySourceReloadResult = mock(PropertySourceReloadResult.class); PropertySourceReloadResult
somePropertySourceReloadResult =
mock(PropertySourceReloadResult.class);
CompositePropertySource somePropertySource = mock(CompositePropertySource.class); CompositePropertySource somePropertySource = mock(CompositePropertySource.class);
List<PropertyChange> emptyChanges = Collections.emptyList(); List<PropertyChange> emptyChanges = Collections.emptyList();
......
package com.ctrip.apollo.client.loader; package com.ctrip.apollo.client.loader;
import com.google.common.base.Function;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ctrip.apollo.client.enums.PropertyChangeType; import com.ctrip.apollo.client.enums.PropertyChangeType;
import com.ctrip.apollo.client.model.ApolloRegistry; import com.ctrip.apollo.client.model.ApolloRegistry;
import com.ctrip.apollo.client.model.PropertyChange; import com.ctrip.apollo.client.model.PropertyChange;
import com.ctrip.apollo.client.model.PropertySourceReloadResult; import com.ctrip.apollo.client.model.PropertySourceReloadResult;
import com.ctrip.apollo.client.util.ConfigUtil; import com.ctrip.apollo.client.util.ConfigUtil;
import com.ctrip.apollo.core.dto.ApolloConfig; import com.ctrip.apollo.core.dto.ApolloConfig;
import com.google.common.base.Function;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.ObjectArrays;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner; import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource; import org.springframework.core.env.PropertySource;
import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.util.ReflectionTestUtils;
...@@ -26,7 +26,12 @@ import java.util.Map; ...@@ -26,7 +26,12 @@ import java.util.Map;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.anyList;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
/** /**
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
...@@ -49,7 +54,9 @@ public class ConfigLoaderManagerTest { ...@@ -49,7 +54,9 @@ public class ConfigLoaderManagerTest {
long someAppId = 100; long someAppId = 100;
long anotherAppId = 101; long anotherAppId = 101;
ApolloRegistry someApolloRegistry = assembleSomeApolloRegistry(someAppId, "someVersion"); ApolloRegistry someApolloRegistry = assembleSomeApolloRegistry(someAppId, "someVersion");
ApolloRegistry anotherApolloRegistry = assembleSomeApolloRegistry(anotherAppId, "anotherVersion"); ApolloRegistry
anotherApolloRegistry =
assembleSomeApolloRegistry(anotherAppId, "anotherVersion");
ApolloConfig someApolloConfig = mock(ApolloConfig.class); ApolloConfig someApolloConfig = mock(ApolloConfig.class);
ApolloConfig anotherApolloConfig = mock(ApolloConfig.class); ApolloConfig anotherApolloConfig = mock(ApolloConfig.class);
Map<String, Object> someMap = mock(Map.class); Map<String, Object> someMap = mock(Map.class);
...@@ -57,9 +64,11 @@ public class ConfigLoaderManagerTest { ...@@ -57,9 +64,11 @@ public class ConfigLoaderManagerTest {
when(someApolloConfig.getAppId()).thenReturn(someAppId); when(someApolloConfig.getAppId()).thenReturn(someAppId);
when(someApolloConfig.getAppId()).thenReturn(anotherAppId); when(someApolloConfig.getAppId()).thenReturn(anotherAppId);
when(configUtil.loadApolloRegistries()).thenReturn(Lists.newArrayList(someApolloRegistry, anotherApolloRegistry)); when(configUtil.loadApolloRegistries())
.thenReturn(Lists.newArrayList(someApolloRegistry, anotherApolloRegistry));
doReturn(someApolloConfig).when(configLoaderManager).loadSingleApolloConfig(someApolloRegistry); doReturn(someApolloConfig).when(configLoaderManager).loadSingleApolloConfig(someApolloRegistry);
doReturn(anotherApolloConfig).when(configLoaderManager).loadSingleApolloConfig(anotherApolloRegistry); doReturn(anotherApolloConfig).when(configLoaderManager)
.loadSingleApolloConfig(anotherApolloRegistry);
when(someApolloConfig.getConfigurations()).thenReturn(someMap); when(someApolloConfig.getConfigurations()).thenReturn(someMap);
when(anotherApolloConfig.getConfigurations()).thenReturn(anotherMap); when(anotherApolloConfig.getConfigurations()).thenReturn(anotherMap);
...@@ -67,10 +76,13 @@ public class ConfigLoaderManagerTest { ...@@ -67,10 +76,13 @@ public class ConfigLoaderManagerTest {
assertEquals(2, result.getPropertySources().size()); assertEquals(2, result.getPropertySources().size());
List<Map<String, Object>> resultMaps = FluentIterable.from(result.getPropertySources()).transform(new Function<PropertySource<?>, Map<String, Object>>() { List<Map<String, Object>>
resultMaps =
FluentIterable.from(result.getPropertySources())
.transform(new Function<PropertySource<?>, Map<String, Object>>() {
@Override @Override
public Map<String, Object> apply(PropertySource<?> input) { public Map<String, Object> apply(PropertySource<?> input) {
return (Map<String, Object>)input.getSource(); return (Map<String, Object>) input.getSource();
} }
}).toList(); }).toList();
...@@ -108,7 +120,8 @@ public class ConfigLoaderManagerTest { ...@@ -108,7 +120,8 @@ public class ConfigLoaderManagerTest {
doReturn(null).when(configLoaderManager).getPreviousApolloConfig(someApolloRegistry); doReturn(null).when(configLoaderManager).getPreviousApolloConfig(someApolloRegistry);
when(someApolloConfig.getConfigurations()).thenReturn(someMap); when(someApolloConfig.getConfigurations()).thenReturn(someMap);
when(configLoader.loadApolloConfig(someApolloRegistry, previousConfig)).thenReturn(someApolloConfig); when(configLoader.loadApolloConfig(someApolloRegistry, previousConfig))
.thenReturn(someApolloConfig);
ApolloConfig result = configLoaderManager.loadSingleApolloConfig(someApolloRegistry); ApolloConfig result = configLoaderManager.loadSingleApolloConfig(someApolloRegistry);
...@@ -122,7 +135,8 @@ public class ConfigLoaderManagerTest { ...@@ -122,7 +135,8 @@ public class ConfigLoaderManagerTest {
ApolloConfig someApolloConfig = mock(ApolloConfig.class); ApolloConfig someApolloConfig = mock(ApolloConfig.class);
Map<String, Object> someMap = mock(Map.class); Map<String, Object> someMap = mock(Map.class);
List<PropertyChange> someChanges = mock(List.class); List<PropertyChange> someChanges = mock(List.class);
ReflectionTestUtils.setField(configLoaderManager, "apolloRegistries", Lists.newArrayList(someApolloRegistry)); ReflectionTestUtils
.setField(configLoaderManager, "apolloRegistries", Lists.newArrayList(someApolloRegistry));
doReturn(someApolloConfig).when(configLoaderManager).loadSingleApolloConfig(someApolloRegistry); doReturn(someApolloConfig).when(configLoaderManager).loadSingleApolloConfig(someApolloRegistry);
when(someApolloConfig.getAppId()).thenReturn(someAppId); when(someApolloConfig.getAppId()).thenReturn(someAppId);
...@@ -133,10 +147,13 @@ public class ConfigLoaderManagerTest { ...@@ -133,10 +147,13 @@ public class ConfigLoaderManagerTest {
assertEquals(1, result.getPropertySource().getPropertySources().size()); assertEquals(1, result.getPropertySource().getPropertySources().size());
assertEquals(someChanges, result.getChanges()); assertEquals(someChanges, result.getChanges());
List<Map<String, Object>> resultMaps = FluentIterable.from(result.getPropertySource().getPropertySources()).transform(new Function<PropertySource<?>, Map<String, Object>>() { List<Map<String, Object>>
resultMaps =
FluentIterable.from(result.getPropertySource().getPropertySources())
.transform(new Function<PropertySource<?>, Map<String, Object>>() {
@Override @Override
public Map<String, Object> apply(PropertySource<?> input) { public Map<String, Object> apply(PropertySource<?> input) {
return (Map<String, Object>)input.getSource(); return (Map<String, Object>) input.getSource();
} }
}).toList(); }).toList();
...@@ -161,7 +178,9 @@ public class ConfigLoaderManagerTest { ...@@ -161,7 +178,9 @@ public class ConfigLoaderManagerTest {
assertEquals(3, changes.size()); assertEquals(3, changes.size());
List<String> changeResult = FluentIterable.from(changes).transform(new Function<PropertyChange, String>() { List<String>
changeResult =
FluentIterable.from(changes).transform(new Function<PropertyChange, String>() {
@Override @Override
public String apply(PropertyChange input) { public String apply(PropertyChange input) {
return String.format("%s-%s", input.getPropertyName(), input.getChangeType()); return String.format("%s-%s", input.getPropertyName(), input.getChangeType());
......
package com.ctrip.apollo.client.loader.impl; package com.ctrip.apollo.client.loader.impl;
import static org.junit.Assert.assertEquals; import com.ctrip.apollo.client.loader.ConfigServiceLocator;
import static org.junit.Assert.assertNull; import com.ctrip.apollo.client.model.ApolloRegistry;
import static org.mockito.Matchers.any; import com.ctrip.apollo.client.util.ConfigUtil;
import static org.mockito.Matchers.anyMap; import com.ctrip.apollo.core.dto.ApolloConfig;
import static org.mockito.Matchers.anyString; import com.ctrip.apollo.core.serivce.ApolloService;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
...@@ -25,11 +17,19 @@ import org.springframework.http.HttpStatus; ...@@ -25,11 +17,19 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import com.ctrip.apollo.client.loader.ConfigServiceLocator; import java.util.ArrayList;
import com.ctrip.apollo.client.model.ApolloRegistry; import java.util.List;
import com.ctrip.apollo.client.util.ConfigUtil;
import com.ctrip.apollo.core.dto.ApolloConfig; import static org.junit.Assert.assertEquals;
import com.ctrip.apollo.core.serivce.ApolloService; import static org.junit.Assert.assertNull;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyMap;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
/** /**
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
...@@ -60,7 +60,6 @@ public class RemoteConfigLoaderTest { ...@@ -60,7 +60,6 @@ public class RemoteConfigLoaderTest {
ApolloRegistry apolloRegistry = assembleSomeApolloRegistry(someAppId, "someVersion"); ApolloRegistry apolloRegistry = assembleSomeApolloRegistry(someAppId, "someVersion");
ApolloConfig previousConfig = null; ApolloConfig previousConfig = null;
ApolloService someService = new ApolloService(); ApolloService someService = new ApolloService();
someService.setHomepageUrl(someServerUrl); someService.setHomepageUrl(someServerUrl);
List<ApolloService> someServices = new ArrayList<>(); List<ApolloService> someServices = new ArrayList<>();
...@@ -90,7 +89,11 @@ public class RemoteConfigLoaderTest { ...@@ -90,7 +89,11 @@ public class RemoteConfigLoaderTest {
when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class),
eq(ApolloConfig.class), anyMap())).thenReturn(someResponse); eq(ApolloConfig.class), anyMap())).thenReturn(someResponse);
ApolloConfig result = remoteConfigLoader.getRemoteConfig(restTemplate, someServerUrl, someClusterName, apolloRegistry, previousConfig); ApolloConfig
result =
remoteConfigLoader
.getRemoteConfig(restTemplate, someServerUrl, someClusterName, apolloRegistry,
previousConfig);
assertEquals(someApolloConfig, result); assertEquals(someApolloConfig, result);
} }
...@@ -109,7 +112,8 @@ public class RemoteConfigLoaderTest { ...@@ -109,7 +112,8 @@ public class RemoteConfigLoaderTest {
when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class),
eq(ApolloConfig.class), anyMap())).thenReturn(someResponse); eq(ApolloConfig.class), anyMap())).thenReturn(someResponse);
remoteConfigLoader.getRemoteConfig(restTemplate, someServerUrl, someClusterName, apolloRegistry, previousConfig); remoteConfigLoader.getRemoteConfig(restTemplate, someServerUrl, someClusterName, apolloRegistry,
previousConfig);
} }
@Test @Test
...@@ -125,7 +129,11 @@ public class RemoteConfigLoaderTest { ...@@ -125,7 +129,11 @@ public class RemoteConfigLoaderTest {
when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class),
eq(ApolloConfig.class), anyMap())).thenReturn(someResponse); eq(ApolloConfig.class), anyMap())).thenReturn(someResponse);
ApolloConfig result = remoteConfigLoader.getRemoteConfig(restTemplate, someServerUrl, someClusterName, apolloRegistry, previousConfig); ApolloConfig
result =
remoteConfigLoader
.getRemoteConfig(restTemplate, someServerUrl, someClusterName, apolloRegistry,
previousConfig);
assertNull(result); assertNull(result);
} }
......
package com.ctrip.apollo.client.util; package com.ctrip.apollo.client.util;
import com.google.common.collect.Lists;
import com.ctrip.apollo.client.constants.Constants; import com.ctrip.apollo.client.constants.Constants;
import com.ctrip.apollo.client.model.ApolloRegistry; import com.ctrip.apollo.client.model.ApolloRegistry;
import com.google.common.collect.Lists;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
...@@ -19,7 +21,12 @@ import java.util.Properties; ...@@ -19,7 +21,12 @@ import java.util.Properties;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
/** /**
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<PatternLayout pattern="[apollo-client][%t]%d %-5p [%c] %m%n"/> <PatternLayout pattern="[apollo-client][%t]%d %-5p [%c] %m%n"/>
</Console> </Console>
<Async name="Async" includeLocation="true"> <Async name="Async" includeLocation="true">
<AppenderRef ref="Console" /> <AppenderRef ref="Console"/>
</Async> </Async>
</appenders> </appenders>
<loggers> <loggers>
......
...@@ -5,6 +5,7 @@ import org.springframework.boot.context.web.SpringBootServletInitializer; ...@@ -5,6 +5,7 @@ import org.springframework.boot.context.web.SpringBootServletInitializer;
/** /**
* Entry point for traditional web app * Entry point for traditional web app
*
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
*/ */
public class ServletInitializer extends SpringBootServletInitializer { public class ServletInitializer extends SpringBootServletInitializer {
......
...@@ -3,11 +3,17 @@ package com.ctrip.apollo.configservice.controller; ...@@ -3,11 +3,17 @@ package com.ctrip.apollo.configservice.controller;
import com.ctrip.apollo.biz.entity.Version; import com.ctrip.apollo.biz.entity.Version;
import com.ctrip.apollo.biz.service.ConfigService; import com.ctrip.apollo.biz.service.ConfigService;
import com.ctrip.apollo.core.dto.ApolloConfig; import com.ctrip.apollo.core.dto.ApolloConfig;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/** /**
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
...@@ -27,7 +33,8 @@ public class ConfigController { ...@@ -27,7 +33,8 @@ public class ConfigController {
Version version = configService.loadVersionByAppIdAndVersionName(appId, versionName); Version version = configService.loadVersionByAppIdAndVersionName(appId, versionName);
if (version == null) { if (version == null) {
response.sendError(HttpServletResponse.SC_NOT_FOUND, response.sendError(HttpServletResponse.SC_NOT_FOUND,
String.format("Could not load version with appId: %d, versionName: %s", appId, versionName)); String.format("Could not load version with appId: %d, versionName: %s", appId,
versionName));
return null; return null;
} }
if (version.getReleaseId() == clientSideReleaseId) { if (version.getReleaseId() == clientSideReleaseId) {
...@@ -41,7 +48,8 @@ public class ConfigController { ...@@ -41,7 +48,8 @@ public class ConfigController {
if (apolloConfig == null) { if (apolloConfig == null) {
response.sendError(HttpServletResponse.SC_NOT_FOUND, response.sendError(HttpServletResponse.SC_NOT_FOUND,
String.format("Could not load config with releaseId: %d, clusterName: %s", version.getReleaseId(), clusterName)); String.format("Could not load config with releaseId: %d, clusterName: %s",
version.getReleaseId(), clusterName));
return null; return null;
} }
......
package com.ctrip.apollo.metaservice.controller; package com.ctrip.apollo.metaservice.controller;
import java.util.ArrayList; import com.ctrip.apollo.core.serivce.ApolloService;
import java.util.List; import com.ctrip.apollo.metaservice.service.DiscoveryService;
import com.netflix.appinfo.InstanceInfo;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import com.ctrip.apollo.core.serivce.ApolloService; import java.util.ArrayList;
import com.ctrip.apollo.metaservice.service.DiscoveryService; import java.util.List;
import com.netflix.appinfo.InstanceInfo;
@RestController @RestController
@RequestMapping("/services") @RequestMapping("/services")
......
package com.ctrip.apollo.metaservice.service; package com.ctrip.apollo.metaservice.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ctrip.apollo.core.ServiceNameConsts; import com.ctrip.apollo.core.ServiceNameConsts;
import com.netflix.appinfo.InstanceInfo; import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClient; import com.netflix.discovery.EurekaClient;
import com.netflix.discovery.shared.Application; import com.netflix.discovery.shared.Application;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service @Service
public class DiscoveryService { public class DiscoveryService {
...@@ -27,7 +27,7 @@ public class DiscoveryService { ...@@ -27,7 +27,7 @@ public class DiscoveryService {
return application != null ? application.getInstances() : new ArrayList<>(); return application != null ? application.getInstances() : new ArrayList<>();
} }
public List<InstanceInfo> getAdminServiceInstances(){ public List<InstanceInfo> getAdminServiceInstances() {
Application application = eurekaClient.getApplication(ServiceNameConsts.APOLLO_ADMINSERVICE); Application application = eurekaClient.getApplication(ServiceNameConsts.APOLLO_ADMINSERVICE);
return application != null ? application.getInstances() : new ArrayList<>(); return application != null ? application.getInstances() : new ArrayList<>();
} }
......
package com.ctrip.apollo.configservice; package com.ctrip.apollo.configservice;
import com.ctrip.apollo.ServerApplication; import com.ctrip.apollo.ServerApplication;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
......
package com.ctrip.apollo.configservice; package com.ctrip.apollo.configservice;
import com.ctrip.apollo.configservice.controller.ConfigControllerTest;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.Suite; import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses; import org.junit.runners.Suite.SuiteClasses;
import com.ctrip.apollo.configservice.controller.ConfigControllerTest;
@RunWith(Suite.class) @RunWith(Suite.class)
@SuiteClasses({ @SuiteClasses({
ConfigControllerTest.class ConfigControllerTest.class
}) })
public class AllTests { public class AllTests {
......
...@@ -2,8 +2,8 @@ package com.ctrip.apollo.configservice.controller; ...@@ -2,8 +2,8 @@ package com.ctrip.apollo.configservice.controller;
import com.ctrip.apollo.biz.entity.Version; import com.ctrip.apollo.biz.entity.Version;
import com.ctrip.apollo.biz.service.ConfigService; import com.ctrip.apollo.biz.service.ConfigService;
import com.ctrip.apollo.configservice.controller.ConfigController;
import com.ctrip.apollo.core.dto.ApolloConfig; import com.ctrip.apollo.core.dto.ApolloConfig;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
...@@ -15,7 +15,14 @@ import javax.servlet.http.HttpServletResponse; ...@@ -15,7 +15,14 @@ import javax.servlet.http.HttpServletResponse;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/** /**
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
...@@ -43,11 +50,17 @@ public class ConfigControllerTest { ...@@ -43,11 +50,17 @@ public class ConfigControllerTest {
HttpServletResponse someResponse = mock(HttpServletResponse.class); HttpServletResponse someResponse = mock(HttpServletResponse.class);
Version someVersion = mock(Version.class); Version someVersion = mock(Version.class);
when(configService.loadVersionByAppIdAndVersionName(someAppId, someVersionName)).thenReturn(someVersion); when(configService.loadVersionByAppIdAndVersionName(someAppId, someVersionName))
.thenReturn(someVersion);
when(someVersion.getReleaseId()).thenReturn(someServerSideNewReleaseId); when(someVersion.getReleaseId()).thenReturn(someServerSideNewReleaseId);
when(configService.loadConfigByVersionAndClusterName(someVersion, someClusterName)).thenReturn(someApolloConfig); when(configService.loadConfigByVersionAndClusterName(someVersion, someClusterName))
.thenReturn(someApolloConfig);
ApolloConfig result = configController.queryConfig(someAppId, someClusterName, someVersionName, someClientSideReleaseId, someResponse); ApolloConfig
result =
configController
.queryConfig(someAppId, someClusterName, someVersionName, someClientSideReleaseId,
someResponse);
assertEquals(someApolloConfig, result); assertEquals(someApolloConfig, result);
verify(configService, times(1)).loadVersionByAppIdAndVersionName(someAppId, someVersionName); verify(configService, times(1)).loadVersionByAppIdAndVersionName(someAppId, someVersionName);
...@@ -62,9 +75,14 @@ public class ConfigControllerTest { ...@@ -62,9 +75,14 @@ public class ConfigControllerTest {
long someClientSideReleaseId = 1; long someClientSideReleaseId = 1;
HttpServletResponse someResponse = mock(HttpServletResponse.class); HttpServletResponse someResponse = mock(HttpServletResponse.class);
when(configService.loadVersionByAppIdAndVersionName(someAppId, someVersionName)).thenReturn(null); when(configService.loadVersionByAppIdAndVersionName(someAppId, someVersionName))
.thenReturn(null);
ApolloConfig result = configController.queryConfig(someAppId, someClusterName, someVersionName, someClientSideReleaseId, someResponse); ApolloConfig
result =
configController
.queryConfig(someAppId, someClusterName, someVersionName, someClientSideReleaseId,
someResponse);
assertNull(result); assertNull(result);
verify(someResponse, times(1)).sendError(eq(HttpServletResponse.SC_NOT_FOUND), anyString()); verify(someResponse, times(1)).sendError(eq(HttpServletResponse.SC_NOT_FOUND), anyString());
...@@ -80,11 +98,17 @@ public class ConfigControllerTest { ...@@ -80,11 +98,17 @@ public class ConfigControllerTest {
HttpServletResponse someResponse = mock(HttpServletResponse.class); HttpServletResponse someResponse = mock(HttpServletResponse.class);
Version someVersion = mock(Version.class); Version someVersion = mock(Version.class);
when(configService.loadVersionByAppIdAndVersionName(someAppId, someVersionName)).thenReturn(someVersion); when(configService.loadVersionByAppIdAndVersionName(someAppId, someVersionName))
.thenReturn(someVersion);
when(someVersion.getReleaseId()).thenReturn(someServerSideNewReleaseId); when(someVersion.getReleaseId()).thenReturn(someServerSideNewReleaseId);
when(configService.loadConfigByVersionAndClusterName(someVersion, someClusterName)).thenReturn(null); when(configService.loadConfigByVersionAndClusterName(someVersion, someClusterName))
.thenReturn(null);
ApolloConfig result = configController.queryConfig(someAppId, someClusterName, someVersionName, someClientSideReleaseId, someResponse); ApolloConfig
result =
configController
.queryConfig(someAppId, someClusterName, someVersionName, someClientSideReleaseId,
someResponse);
assertNull(result); assertNull(result);
verify(someResponse, times(1)).sendError(eq(HttpServletResponse.SC_NOT_FOUND), anyString()); verify(someResponse, times(1)).sendError(eq(HttpServletResponse.SC_NOT_FOUND), anyString());
...@@ -100,13 +124,19 @@ public class ConfigControllerTest { ...@@ -100,13 +124,19 @@ public class ConfigControllerTest {
HttpServletResponse someResponse = mock(HttpServletResponse.class); HttpServletResponse someResponse = mock(HttpServletResponse.class);
Version someVersion = mock(Version.class); Version someVersion = mock(Version.class);
when(configService.loadVersionByAppIdAndVersionName(someAppId, someVersionName)).thenReturn(someVersion); when(configService.loadVersionByAppIdAndVersionName(someAppId, someVersionName))
.thenReturn(someVersion);
when(someVersion.getReleaseId()).thenReturn(someServerSideReleaseId); when(someVersion.getReleaseId()).thenReturn(someServerSideReleaseId);
ApolloConfig result = configController.queryConfig(someAppId, someClusterName, someVersionName, someClientSideReleaseId, someResponse); ApolloConfig
result =
configController
.queryConfig(someAppId, someClusterName, someVersionName, someClientSideReleaseId,
someResponse);
assertNull(result); assertNull(result);
verify(someResponse, times(1)).setStatus(HttpServletResponse.SC_NOT_MODIFIED); verify(someResponse, times(1)).setStatus(HttpServletResponse.SC_NOT_MODIFIED);
verify(configService, never()).loadConfigByVersionAndClusterName(any(Version.class), anyString()); verify(configService, never())
.loadConfigByVersionAndClusterName(any(Version.class), anyString());
} }
} }
...@@ -2,7 +2,7 @@ package com.ctrip.apollo; ...@@ -2,7 +2,7 @@ package com.ctrip.apollo;
public class Apollo { public class Apollo {
public final static String VERSION = "java-0.0.1-SNAPSHOT"; public static final String VERSION = "java-0.0.1-SNAPSHOT";
private static Env m_env; private static Env m_env;
......
package com.ctrip.apollo.core; package com.ctrip.apollo.core;
import com.ctrip.apollo.Apollo.Env;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.ctrip.apollo.Apollo.Env;
public class MetaDomainConsts { public class MetaDomainConsts {
public static final String DEFAULT_PORT = "8080"; public static final String DEFAULT_PORT = "8080";
......
package com.ctrip.apollo.core.dto; package com.ctrip.apollo.core.dto;
import com.google.common.base.MoreObjects;
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.MoreObjects;
import java.util.Comparator;
import java.util.Map; import java.util.Map;
/** /**
...@@ -81,11 +81,11 @@ public class ApolloConfig implements Comparable<ApolloConfig> { ...@@ -81,11 +81,11 @@ public class ApolloConfig implements Comparable<ApolloConfig> {
} }
@Override @Override
public int compareTo(ApolloConfig o) { public int compareTo(ApolloConfig toCompare) {
if (o == null || this.getOrder() > o.getOrder()) { if (toCompare == null || this.getOrder() > toCompare.getOrder()) {
return 1; return 1;
} }
if (o.getOrder() > this.getOrder()) { if (toCompare.getOrder() > this.getOrder()) {
return -1; return -1;
} }
return 0; return 0;
......
...@@ -22,15 +22,15 @@ public class ConfigItemDTO { ...@@ -22,15 +22,15 @@ public class ConfigItemDTO {
private Date dataChangeCreatedTime; private Date dataChangeCreatedTime;
private String DataChangeLastModifiedBy; private String dataChangeLastModifiedBy;
private Date dataChangeLastModifiedTime; private Date dataChangeLastModifiedTime;
public ConfigItemDTO(){ public ConfigItemDTO() {
} }
public ConfigItemDTO(String key, String value){ public ConfigItemDTO(String key, String value) {
this.key = key; this.key = key;
this.value = value; this.value = value;
} }
...@@ -100,11 +100,11 @@ public class ConfigItemDTO { ...@@ -100,11 +100,11 @@ public class ConfigItemDTO {
} }
public String getDataChangeLastModifiedBy() { public String getDataChangeLastModifiedBy() {
return DataChangeLastModifiedBy; return dataChangeLastModifiedBy;
} }
public void setDataChangeLastModifiedBy(String dataChangeLastModifiedBy) { public void setDataChangeLastModifiedBy(String dataChangeLastModifiedBy) {
DataChangeLastModifiedBy = dataChangeLastModifiedBy; this.dataChangeLastModifiedBy = dataChangeLastModifiedBy;
} }
public Date getDataChangeLastModifiedTime() { public Date getDataChangeLastModifiedTime() {
......
...@@ -12,7 +12,7 @@ public class VersionDTO { ...@@ -12,7 +12,7 @@ public class VersionDTO {
private Long parentVersion; private Long parentVersion;
public VersionDTO(){ public VersionDTO() {
} }
......
package com.ctrip.apollo.core.utils; package com.ctrip.apollo.core.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
...@@ -7,22 +10,19 @@ import java.util.concurrent.ThreadFactory; ...@@ -7,22 +10,19 @@ import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ApolloThreadFactory implements ThreadFactory { public class ApolloThreadFactory implements ThreadFactory {
private static Logger log = LoggerFactory.getLogger(ApolloThreadFactory.class); private static Logger log = LoggerFactory.getLogger(ApolloThreadFactory.class);
private final AtomicLong m_threadNumber = new AtomicLong(1); private final AtomicLong threadNumber = new AtomicLong(1);
private final String m_namePrefix; private final String namePrefix;
private final boolean m_daemon; private final boolean daemon;
private final static ThreadGroup m_threadGroup = new ThreadGroup("Apollo"); private static final ThreadGroup threadGroup = new ThreadGroup("Apollo");
public static ThreadGroup getThreadGroup() { public static ThreadGroup getThreadGroup() {
return m_threadGroup; return threadGroup;
} }
public static ThreadFactory create(String namePrefix, boolean daemon) { public static ThreadFactory create(String namePrefix, boolean daemon) {
...@@ -40,15 +40,15 @@ public class ApolloThreadFactory implements ThreadFactory { ...@@ -40,15 +40,15 @@ public class ApolloThreadFactory implements ThreadFactory {
while (System.currentTimeMillis() < expire) { while (System.currentTimeMillis() < expire) {
classify(alives, dies, new ClassifyStandard<Thread>() { classify(alives, dies, new ClassifyStandard<Thread>() {
@Override @Override
public boolean satisfy(Thread t) { public boolean satisfy(Thread thread) {
return !t.isAlive() || t.isInterrupted() || t.isDaemon(); return !thread.isAlive() || thread.isInterrupted() || thread.isDaemon();
} }
}); });
if (alives.size() > 0) { if (alives.size() > 0) {
log.info("Alive apollo threads: {}", alives); log.info("Alive apollo threads: {}", alives);
try { try {
TimeUnit.SECONDS.sleep(2); TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) { } catch (InterruptedException ex) {
// ignore // ignore
} }
} else { } else {
...@@ -56,36 +56,38 @@ public class ApolloThreadFactory implements ThreadFactory { ...@@ -56,36 +56,38 @@ public class ApolloThreadFactory implements ThreadFactory {
return true; return true;
} }
} }
log.warn("Some apollo threads are still alive but expire time has reached, alive threads: {}", alives); log.warn("Some apollo threads are still alive but expire time has reached, alive threads: {}",
alives);
return false; return false;
} }
private static interface ClassifyStandard<T> { private static interface ClassifyStandard<T> {
boolean satisfy(T t); boolean satisfy(T thread);
} }
private static <T> void classify(Set<T> src, Set<T> des, ClassifyStandard<T> standard) { private static <T> void classify(Set<T> src, Set<T> des, ClassifyStandard<T> standard) {
Set<T> s = new HashSet<>(); Set<T> set = new HashSet<>();
for (T t : src) { for (T t : src) {
if (standard.satisfy(t)) { if (standard.satisfy(t)) {
s.add(t); set.add(t);
} }
} }
src.removeAll(s); src.removeAll(set);
des.addAll(s); des.addAll(set);
} }
private ApolloThreadFactory(String namePrefix, boolean daemon) { private ApolloThreadFactory(String namePrefix, boolean daemon) {
m_namePrefix = namePrefix; this.namePrefix = namePrefix;
m_daemon = daemon; this.daemon = daemon;
} }
public Thread newThread(Runnable r) { public Thread newThread(Runnable runnable) {
Thread t = new Thread(m_threadGroup, r,// Thread thread = new Thread(threadGroup, runnable,//
m_threadGroup.getName() + "-" + m_namePrefix + "-" + m_threadNumber.getAndIncrement()); threadGroup.getName() + "-" + namePrefix + "-" + threadNumber.getAndIncrement());
t.setDaemon(m_daemon); thread.setDaemon(daemon);
if (t.getPriority() != Thread.NORM_PRIORITY) if (thread.getPriority() != Thread.NORM_PRIORITY) {
t.setPriority(Thread.NORM_PRIORITY); thread.setPriority(Thread.NORM_PRIORITY);
return t; }
return thread;
} }
} }
...@@ -24,8 +24,7 @@ public class StringUtils { ...@@ -24,8 +24,7 @@ public class StringUtils {
* NOTE: This method changed in Lang version 2.0. It no longer trims the String. That functionality is available in isBlank(). * NOTE: This method changed in Lang version 2.0. It no longer trims the String. That functionality is available in isBlank().
* </p> * </p>
* *
* @param str * @param str the String to check, may be null
* the String to check, may be null
* @return <code>true</code> if the String is empty or null * @return <code>true</code> if the String is empty or null
*/ */
public static boolean isEmpty(String str) { public static boolean isEmpty(String str) {
...@@ -45,8 +44,7 @@ public class StringUtils { ...@@ -45,8 +44,7 @@ public class StringUtils {
* StringUtils.isBlank(" bob ") = false * StringUtils.isBlank(" bob ") = false
* </pre> * </pre>
* *
* @param str * @param str the String to check, may be null
* the String to check, may be null
* @return <code>true</code> if the String is null, empty or whitespace * @return <code>true</code> if the String is null, empty or whitespace
*/ */
public static boolean isBlank(String str) { public static boolean isBlank(String str) {
...@@ -80,8 +78,7 @@ public class StringUtils { ...@@ -80,8 +78,7 @@ public class StringUtils {
* StringUtils.trimToNull(" abc ") = "abc" * StringUtils.trimToNull(" abc ") = "abc"
* </pre> * </pre>
* *
* @param str * @param str the String to be trimmed, may be null
* the String to be trimmed, may be null
* @return the trimmed String, <code>null</code> if only chars &lt;= 32, empty or null String input * @return the trimmed String, <code>null</code> if only chars &lt;= 32, empty or null String input
* @since 2.0 * @since 2.0
*/ */
...@@ -108,8 +105,7 @@ public class StringUtils { ...@@ -108,8 +105,7 @@ public class StringUtils {
* StringUtils.trimToEmpty(" abc ") = "abc" * StringUtils.trimToEmpty(" abc ") = "abc"
* </pre> * </pre>
* *
* @param str * @param str the String to be trimmed, may be null
* the String to be trimmed, may be null
* @return the trimmed String, or an empty String if <code>null</code> input * @return the trimmed String, or an empty String if <code>null</code> input
* @since 2.0 * @since 2.0
*/ */
...@@ -140,8 +136,7 @@ public class StringUtils { ...@@ -140,8 +136,7 @@ public class StringUtils {
* StringUtils.trim(" abc ") = "abc" * StringUtils.trim(" abc ") = "abc"
* </pre> * </pre>
* *
* @param str * @param str the String to be trimmed, may be null
* the String to be trimmed, may be null
* @return the trimmed string, <code>null</code> if null String input * @return the trimmed string, <code>null</code> if null String input
*/ */
public static String trim(String str) { public static String trim(String str) {
...@@ -166,12 +161,10 @@ public class StringUtils { ...@@ -166,12 +161,10 @@ public class StringUtils {
* StringUtils.equals("abc", "ABC") = false * StringUtils.equals("abc", "ABC") = false
* </pre> * </pre>
* *
* @see java.lang.String#equals(Object) * @param str1 the first String, may be null
* @param str1 * @param str2 the second String, may be null
* the first String, may be null
* @param str2
* the second String, may be null
* @return <code>true</code> if the Strings are equal, case sensitive, or both <code>null</code> * @return <code>true</code> if the Strings are equal, case sensitive, or both <code>null</code>
* @see java.lang.String#equals(Object)
*/ */
public static boolean equals(String str1, String str2) { public static boolean equals(String str1, String str2) {
return str1 == null ? str2 == null : str1.equals(str2); return str1 == null ? str2 == null : str1.equals(str2);
...@@ -195,12 +188,10 @@ public class StringUtils { ...@@ -195,12 +188,10 @@ public class StringUtils {
* StringUtils.equalsIgnoreCase("abc", "ABC") = true * StringUtils.equalsIgnoreCase("abc", "ABC") = true
* </pre> * </pre>
* *
* @see java.lang.String#equalsIgnoreCase(String) * @param str1 the first String, may be null
* @param str1 * @param str2 the second String, may be null
* the first String, may be null
* @param str2
* the second String, may be null
* @return <code>true</code> if the Strings are equal, case insensitive, or both <code>null</code> * @return <code>true</code> if the Strings are equal, case insensitive, or both <code>null</code>
* @see java.lang.String#equalsIgnoreCase(String)
*/ */
public static boolean equalsIgnoreCase(String str1, String str2) { public static boolean equalsIgnoreCase(String str1, String str2) {
return str1 == null ? str2 == null : str1.equalsIgnoreCase(str2); return str1 == null ? str2 == null : str1.equalsIgnoreCase(str2);
...@@ -224,18 +215,37 @@ public class StringUtils { ...@@ -224,18 +215,37 @@ public class StringUtils {
* StringUtils.startsWith("ABCDEF", "abc") = false * StringUtils.startsWith("ABCDEF", "abc") = false
* </pre> * </pre>
* *
* @see java.lang.String#startsWith(String) * @param str the String to check, may be null
* @param str * @param prefix the prefix to find, may be null
* the String to check, may be null
* @param prefix
* the prefix to find, may be null
* @return <code>true</code> if the String starts with the prefix, case sensitive, or both <code>null</code> * @return <code>true</code> if the String starts with the prefix, case sensitive, or both <code>null</code>
* @see java.lang.String#startsWith(String)
* @since 2.4 * @since 2.4
*/ */
public static boolean startsWith(String str, String prefix) { public static boolean startsWith(String str, String prefix) {
return startsWith(str, prefix, false); return startsWith(str, prefix, false);
} }
/**
* <p>
* Check if a String starts with a specified prefix (optionally case insensitive).
* </p>
*
* @param str the String to check, may be null
* @param prefix the prefix to find, may be null
* @param ignoreCase inidicates whether the compare should ignore case (case insensitive) or not.
* @return <code>true</code> if the String starts with the prefix or both <code>null</code>
* @see java.lang.String#startsWith(String)
*/
private static boolean startsWith(String str, String prefix, boolean ignoreCase) {
if (str == null || prefix == null) {
return (str == null && prefix == null);
}
if (prefix.length() > str.length()) {
return false;
}
return str.regionMatches(ignoreCase, 0, prefix, 0, prefix.length());
}
/** /**
* <p> * <p>
* Case insensitive check if a String starts with a specified prefix. * Case insensitive check if a String starts with a specified prefix.
...@@ -254,12 +264,10 @@ public class StringUtils { ...@@ -254,12 +264,10 @@ public class StringUtils {
* StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true * StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true
* </pre> * </pre>
* *
* @see java.lang.String#startsWith(String) * @param str the String to check, may be null
* @param str * @param prefix the prefix to find, may be null
* the String to check, may be null
* @param prefix
* the prefix to find, may be null
* @return <code>true</code> if the String starts with the prefix, case insensitive, or both <code>null</code> * @return <code>true</code> if the String starts with the prefix, case insensitive, or both <code>null</code>
* @see java.lang.String#startsWith(String)
* @since 2.4 * @since 2.4
*/ */
public static boolean startsWithIgnoreCase(String str, String prefix) { public static boolean startsWithIgnoreCase(String str, String prefix) {
...@@ -286,8 +294,7 @@ public class StringUtils { ...@@ -286,8 +294,7 @@ public class StringUtils {
* StringUtils.isNumeric("12.3") = false * StringUtils.isNumeric("12.3") = false
* </pre> * </pre>
* *
* @param str * @param str the String to check, may be null
* the String to check, may be null
* @return <code>true</code> if only contains digits, and is non-null * @return <code>true</code> if only contains digits, and is non-null
*/ */
public static boolean isNumeric(String str) { public static boolean isNumeric(String str) {
...@@ -303,30 +310,6 @@ public class StringUtils { ...@@ -303,30 +310,6 @@ public class StringUtils {
return true; return true;
} }
/**
* <p>
* Check if a String starts with a specified prefix (optionally case insensitive).
* </p>
*
* @see java.lang.String#startsWith(String)
* @param str
* the String to check, may be null
* @param prefix
* the prefix to find, may be null
* @param ignoreCase
* inidicates whether the compare should ignore case (case insensitive) or not.
* @return <code>true</code> if the String starts with the prefix or both <code>null</code>
*/
private static boolean startsWith(String str, String prefix, boolean ignoreCase) {
if (str == null || prefix == null) {
return (str == null && prefix == null);
}
if (prefix.length() > str.length()) {
return false;
}
return str.regionMatches(ignoreCase, 0, prefix, 0, prefix.length());
}
public static interface StringFormatter<T> { public static interface StringFormatter<T> {
public String format(T obj); public String format(T obj);
} }
...@@ -340,7 +323,8 @@ public class StringUtils { ...@@ -340,7 +323,8 @@ public class StringUtils {
}); });
} }
public static <T> String join(Collection<T> collection, String separator, StringFormatter<T> formatter) { public static <T> String join(Collection<T> collection, String separator,
StringFormatter<T> formatter) {
Iterator<T> iterator = collection.iterator(); Iterator<T> iterator = collection.iterator();
// handle null, zero and one elements before building a buffer // handle null, zero and one elements before building a buffer
if (iterator == null) { if (iterator == null) {
......
package com.ctrip.apollo.demo; package com.ctrip.apollo.demo;
import com.ctrip.apollo.client.ApolloConfigManager; import com.ctrip.apollo.client.ApolloConfigManager;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
......
...@@ -6,8 +6,8 @@ import com.ctrip.apollo.client.model.PropertyChange; ...@@ -6,8 +6,8 @@ import com.ctrip.apollo.client.model.PropertyChange;
import com.ctrip.apollo.client.util.ConfigUtil; import com.ctrip.apollo.client.util.ConfigUtil;
import com.ctrip.apollo.demo.model.Config; import com.ctrip.apollo.demo.model.Config;
import com.ctrip.apollo.demo.service.DemoService; import com.ctrip.apollo.demo.service.DemoService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.scope.refresh.RefreshScope;
import org.springframework.context.annotation.PropertySource; import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
......
...@@ -2,6 +2,7 @@ package com.ctrip.apollo.demo.exception; ...@@ -2,6 +2,7 @@ package com.ctrip.apollo.demo.exception;
import com.ctrip.apollo.demo.model.ErrorResult; import com.ctrip.apollo.demo.model.ErrorResult;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
...@@ -17,7 +18,8 @@ public class RestExceptionHandler { ...@@ -17,7 +18,8 @@ public class RestExceptionHandler {
@ExceptionHandler(Exception.class) @ExceptionHandler(Exception.class)
ResponseEntity<ErrorResult> handleWebExceptions(Exception ex, ResponseEntity<ErrorResult> handleWebExceptions(Exception ex,
WebRequest request) throws JsonProcessingException { WebRequest request)
throws JsonProcessingException {
ErrorResult error = new ErrorResult(HttpStatus.INTERNAL_SERVER_ERROR.value(), ex.getMessage()); ErrorResult error = new ErrorResult(HttpStatus.INTERNAL_SERVER_ERROR.value(), ex.getMessage());
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(error); return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(error);
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<PatternLayout pattern="[apollo-demo][%t]%d %-5p [%c] %m%n"/> <PatternLayout pattern="[apollo-demo][%t]%d %-5p [%c] %m%n"/>
</Console> </Console>
<Async name="Async" includeLocation="true"> <Async name="Async" includeLocation="true">
<AppenderRef ref="Console" /> <AppenderRef ref="Console"/>
</Async> </Async>
</appenders> </appenders>
<loggers> <loggers>
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<title>Apollo Config Client</title> <title>Apollo Config Client</title>
<link rel="stylesheet" type="text/css" href="http://apps.bdimg.com/libs/bootstrap/3.3.0/css/bootstrap.min.css"/> <link rel="stylesheet" type="text/css" href="http://apps.bdimg.com/libs/bootstrap/3.3.0/css/bootstrap.min.css"/>
<link rel="stylesheet" type="text/css" href="/styles/angular-toastr-1.4.1.min.css"/> <link rel="stylesheet" type="text/css" href="/styles/angular-toastr-1.4.1.min.css"/>
<link rel='stylesheet' href='/styles/loading-bar.min.css' type='text/css' media='all' /> <link rel='stylesheet' href='/styles/loading-bar.min.css' type='text/css' media='all'/>
<link rel="stylesheet" type="text/css" href="/styles/app.css"/> <link rel="stylesheet" type="text/css" href="/styles/app.css"/>
<script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/1.9.1/jquery.min.js"></script> <script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="http://apps.bdimg.com/libs/angular.js/1.3.9/angular.min.js"></script> <script type="text/javascript" src="http://apps.bdimg.com/libs/angular.js/1.3.9/angular.min.js"></script>
......
!function(){"use strict";function t(t,e,s,n,o,r,a){function i(t){if(t)d(t.toastId);else for(var e=0;e<O.length;e++)d(O[e].toastId)}function l(t,e,s){var n=m().iconClasses.error;return g(n,t,e,s)}function c(t,e,s){var n=m().iconClasses.info;return g(n,t,e,s)}function u(t,e,s){var n=m().iconClasses.success;return g(n,t,e,s)}function p(t,e,s){var n=m().iconClasses.warning;return g(n,t,e,s)}function d(e,s){function n(t){for(var e=0;e<O.length;e++)if(O[e].toastId===t)return O[e]}function o(){return!O.length}var i=n(e);i&&!i.deleting&&(i.deleting=!0,i.isOpened=!1,t.leave(i.el).then(function(){i.scope.options.onHidden&&i.scope.options.onHidden(s),i.scope.$destroy();var t=O.indexOf(i);delete B[i.scope.message],O.splice(t,1);var e=r.maxOpened;e&&O.length>=e&&O[e-1].open.resolve(),o()&&(h.remove(),h=null,T=a.defer())}))}function g(t,e,s,n){return angular.isObject(s)&&(n=s,s=null),v({iconClass:t,message:e,optionsOverride:n,title:s})}function m(){return angular.extend({},r)}function f(e){if(h)return T.promise;h=angular.element("<div></div>"),h.attr("id",e.containerId),h.addClass(e.positionClass),h.css({"pointer-events":"auto"});var s=angular.element(document.querySelector(e.target));if(!s||!s.length)throw"Target for toasts doesn't exist";return t.enter(h,s).then(function(){T.resolve()}),T.promise}function v(s){function r(t,e,s){s.allowHtml?(t.scope.allowHtml=!0,t.scope.title=o.trustAsHtml(e.title),t.scope.message=o.trustAsHtml(e.message)):(t.scope.title=e.title,t.scope.message=e.message),t.scope.toastType=t.iconClass,t.scope.toastId=t.toastId,t.scope.options={extendedTimeOut:s.extendedTimeOut,messageClass:s.messageClass,onHidden:s.onHidden,onShown:s.onShown,progressBar:s.progressBar,tapToDismiss:s.tapToDismiss,timeOut:s.timeOut,titleClass:s.titleClass,toastClass:s.toastClass},s.closeButton&&(t.scope.options.closeHtml=s.closeHtml)}function i(){function t(t){for(var e=["containerId","iconClasses","maxOpened","newestOnTop","positionClass","preventDuplicates","preventOpenDuplicates","templates"],s=0,n=e.length;n>s;s++)delete t[e[s]];return t}var e={toastId:C++,isOpened:!1,scope:n.$new(),open:a.defer()};return e.iconClass=s.iconClass,s.optionsOverride&&(p=angular.extend(p,t(s.optionsOverride)),e.iconClass=s.optionsOverride.iconClass||e.iconClass),r(e,s,p),e.el=l(e.scope),e}function l(t){var s=angular.element("<div toast></div>"),n=e.get("$compile");return n(s)(t)}function c(){return p.maxOpened&&O.length<=p.maxOpened||!p.maxOpened}function u(){var t=p.preventDuplicates&&s.message===w,e=p.preventOpenDuplicates&&B[s.message];return t||e?!0:(w=s.message,B[s.message]=!0,!1)}var p=m();if(!u()){var g=i();if(O.push(g),p.autoDismiss&&p.maxOpened>0)for(var v=O.slice(0,O.length-p.maxOpened),T=0,$=v.length;$>T;T++)d(v[T].toastId);return c()&&g.open.resolve(),g.open.promise.then(function(){f(p).then(function(){if(g.isOpened=!0,p.newestOnTop)t.enter(g.el,h).then(function(){g.scope.init()});else{var e=h[0].lastChild?angular.element(h[0].lastChild):null;t.enter(g.el,h,e).then(function(){g.scope.init()})}})}),g}}var h,C=0,O=[],w="",B={},T=a.defer(),$={clear:i,error:l,info:c,remove:d,success:u,warning:p};return $}angular.module("toastr",[]).factory("toastr",t),t.$inject=["$animate","$injector","$document","$rootScope","$sce","toastrConfig","$q"]}(),function(){"use strict";angular.module("toastr").constant("toastrConfig",{allowHtml:!1,autoDismiss:!1,closeButton:!1,closeHtml:"<button>&times;</button>",containerId:"toast-container",extendedTimeOut:1e3,iconClasses:{error:"toast-error",info:"toast-info",success:"toast-success",warning:"toast-warning"},maxOpened:0,messageClass:"toast-message",newestOnTop:!0,onHidden:null,onShown:null,positionClass:"toast-top-right",preventDuplicates:!1,preventOpenDuplicates:!1,progressBar:!1,tapToDismiss:!0,target:"body",templates:{toast:"directives/toast/toast.html",progressbar:"directives/progressbar/progressbar.html"},timeOut:5e3,titleClass:"toast-title",toastClass:"toast"})}(),function(){"use strict";function t(t){function e(t,e,s,n){function o(){var t=(i-(new Date).getTime())/a*100;e.css("width",t+"%")}var r,a,i;n.progressBar=t,t.start=function(t){r&&clearInterval(r),a=parseFloat(t),i=(new Date).getTime()+a,r=setInterval(o,10)},t.stop=function(){r&&clearInterval(r)},t.$on("$destroy",function(){clearInterval(r)})}return{replace:!0,require:"^toast",templateUrl:function(){return t.templates.progressbar},link:e}}angular.module("toastr").directive("progressBar",t),t.$inject=["toastrConfig"]}(),function(){"use strict";function t(){this.progressBar=null,this.startProgressBar=function(t){this.progressBar&&this.progressBar.start(t)},this.stopProgressBar=function(){this.progressBar&&this.progressBar.stop()}}angular.module("toastr").controller("ToastController",t)}(),function(){"use strict";function t(t,e,s,n){function o(s,o,r,a){function i(t){return a.startProgressBar(t),e(function(){a.stopProgressBar(),n.remove(s.toastId)},t,1)}function l(){s.progressBar=!1,a.stopProgressBar()}function c(){return s.options.closeHtml}var u;if(s.toastClass=s.options.toastClass,s.titleClass=s.options.titleClass,s.messageClass=s.options.messageClass,s.progressBar=s.options.progressBar,c()){var p=angular.element(s.options.closeHtml),d=t.get("$compile");p.addClass("toast-close-button"),p.attr("ng-click","close()"),d(p)(s),o.prepend(p)}s.init=function(){s.options.timeOut&&(u=i(s.options.timeOut)),s.options.onShown&&s.options.onShown()},o.on("mouseenter",function(){l(),u&&e.cancel(u)}),s.tapToast=function(){s.options.tapToDismiss&&s.close(!0)},s.close=function(t){n.remove(s.toastId,t)},o.on("mouseleave",function(){(0!==s.options.timeOut||0!==s.options.extendedTimeOut)&&(s.$apply(function(){s.progressBar=s.options.progressBar}),u=i(s.options.extendedTimeOut))})}return{replace:!0,templateUrl:function(){return s.templates.toast},controller:"ToastController",link:o}}angular.module("toastr").directive("toast",t),t.$inject=["$injector","$interval","toastrConfig","toastr"]}(),angular.module("toastr").run(["$templateCache",function(t){t.put("directives/progressbar/progressbar.html",'<div class="toast-progress"></div>\n'),t.put("directives/toast/toast.html",'<div class="{{toastClass}} {{toastType}}" ng-click="tapToast()">\n <div ng-switch on="allowHtml">\n <div ng-switch-default ng-if="title" class="{{titleClass}}">{{title}}</div>\n <div ng-switch-default class="{{messageClass}}">{{message}}</div>\n <div ng-switch-when="true" ng-if="title" class="{{titleClass}}" ng-bind-html="title"></div>\n <div ng-switch-when="true" class="{{messageClass}}" ng-bind-html="message"></div>\n </div>\n <progress-bar ng-if="progressBar"></progress-bar>\n</div>\n')}]); !function () {
\ No newline at end of file "use strict";
function t(t, e, s, n, o, r, a) {
function i(t) {
if (t)d(t.toastId); else for (var e = 0; e < O.length; e++)d(O[e].toastId)
}
function l(t, e, s) {
var n = m().iconClasses.error;
return g(n, t, e, s)
}
function c(t, e, s) {
var n = m().iconClasses.info;
return g(n, t, e, s)
}
function u(t, e, s) {
var n = m().iconClasses.success;
return g(n, t, e, s)
}
function p(t, e, s) {
var n = m().iconClasses.warning;
return g(n, t, e, s)
}
function d(e, s) {
function n(t) {
for (var e = 0; e < O.length; e++)if (O[e].toastId === t)return O[e]
}
function o() {
return !O.length
}
var i = n(e);
i && !i.deleting && (i.deleting = !0, i.isOpened = !1, t.leave(i.el).then(function () {
i.scope.options.onHidden && i.scope.options.onHidden(s), i.scope.$destroy();
var t = O.indexOf(i);
delete B[i.scope.message], O.splice(t, 1);
var e = r.maxOpened;
e && O.length >= e && O[e - 1].open.resolve(), o() && (h.remove(), h = null, T = a.defer())
}))
}
function g(t, e, s, n) {
return angular.isObject(s) && (n = s, s = null), v({iconClass: t, message: e, optionsOverride: n, title: s})
}
function m() {
return angular.extend({}, r)
}
function f(e) {
if (h)return T.promise;
h = angular.element("<div></div>"), h.attr("id", e.containerId), h.addClass(e.positionClass), h.css({"pointer-events": "auto"});
var s = angular.element(document.querySelector(e.target));
if (!s || !s.length)throw"Target for toasts doesn't exist";
return t.enter(h, s).then(function () {
T.resolve()
}), T.promise
}
function v(s) {
function r(t, e, s) {
s.allowHtml ? (t.scope.allowHtml = !0, t.scope.title = o.trustAsHtml(e.title), t.scope.message = o.trustAsHtml(e.message)) : (t.scope.title = e.title, t.scope.message = e.message), t.scope.toastType = t.iconClass, t.scope.toastId = t.toastId, t.scope.options = {
extendedTimeOut: s.extendedTimeOut,
messageClass: s.messageClass,
onHidden: s.onHidden,
onShown: s.onShown,
progressBar: s.progressBar,
tapToDismiss: s.tapToDismiss,
timeOut: s.timeOut,
titleClass: s.titleClass,
toastClass: s.toastClass
}, s.closeButton && (t.scope.options.closeHtml = s.closeHtml)
}
function i() {
function t(t) {
for (var e = ["containerId", "iconClasses", "maxOpened", "newestOnTop", "positionClass", "preventDuplicates", "preventOpenDuplicates", "templates"], s = 0, n = e.length; n > s; s++)delete t[e[s]];
return t
}
var e = {toastId: C++, isOpened: !1, scope: n.$new(), open: a.defer()};
return e.iconClass = s.iconClass, s.optionsOverride && (p = angular.extend(p, t(s.optionsOverride)), e.iconClass = s.optionsOverride.iconClass || e.iconClass), r(e, s, p), e.el = l(e.scope), e
}
function l(t) {
var s = angular.element("<div toast></div>"), n = e.get("$compile");
return n(s)(t)
}
function c() {
return p.maxOpened && O.length <= p.maxOpened || !p.maxOpened
}
function u() {
var t = p.preventDuplicates && s.message === w, e = p.preventOpenDuplicates && B[s.message];
return t || e ? !0 : (w = s.message, B[s.message] = !0, !1)
}
var p = m();
if (!u()) {
var g = i();
if (O.push(g), p.autoDismiss && p.maxOpened > 0)for (var v = O.slice(0, O.length - p.maxOpened), T = 0, $ = v.length; $ > T; T++)d(v[T].toastId);
return c() && g.open.resolve(), g.open.promise.then(function () {
f(p).then(function () {
if (g.isOpened = !0, p.newestOnTop)t.enter(g.el, h).then(function () {
g.scope.init()
}); else {
var e = h[0].lastChild ? angular.element(h[0].lastChild) : null;
t.enter(g.el, h, e).then(function () {
g.scope.init()
})
}
})
}), g
}
}
var h, C = 0, O = [], w = "", B = {}, T = a.defer(), $ = {
clear: i,
error: l,
info: c,
remove: d,
success: u,
warning: p
};
return $
}
angular.module("toastr", []).factory("toastr", t), t.$inject = ["$animate", "$injector", "$document", "$rootScope", "$sce", "toastrConfig", "$q"]
}(), function () {
"use strict";
angular.module("toastr").constant("toastrConfig", {
allowHtml: !1,
autoDismiss: !1,
closeButton: !1,
closeHtml: "<button>&times;</button>",
containerId: "toast-container",
extendedTimeOut: 1e3,
iconClasses: {error: "toast-error", info: "toast-info", success: "toast-success", warning: "toast-warning"},
maxOpened: 0,
messageClass: "toast-message",
newestOnTop: !0,
onHidden: null,
onShown: null,
positionClass: "toast-top-right",
preventDuplicates: !1,
preventOpenDuplicates: !1,
progressBar: !1,
tapToDismiss: !0,
target: "body",
templates: {toast: "directives/toast/toast.html", progressbar: "directives/progressbar/progressbar.html"},
timeOut: 5e3,
titleClass: "toast-title",
toastClass: "toast"
})
}(), function () {
"use strict";
function t(t) {
function e(t, e, s, n) {
function o() {
var t = (i - (new Date).getTime()) / a * 100;
e.css("width", t + "%")
}
var r, a, i;
n.progressBar = t, t.start = function (t) {
r && clearInterval(r), a = parseFloat(t), i = (new Date).getTime() + a, r = setInterval(o, 10)
}, t.stop = function () {
r && clearInterval(r)
}, t.$on("$destroy", function () {
clearInterval(r)
})
}
return {
replace: !0, require: "^toast", templateUrl: function () {
return t.templates.progressbar
}, link: e
}
}
angular.module("toastr").directive("progressBar", t), t.$inject = ["toastrConfig"]
}(), function () {
"use strict";
function t() {
this.progressBar = null, this.startProgressBar = function (t) {
this.progressBar && this.progressBar.start(t)
}, this.stopProgressBar = function () {
this.progressBar && this.progressBar.stop()
}
}
angular.module("toastr").controller("ToastController", t)
}(), function () {
"use strict";
function t(t, e, s, n) {
function o(s, o, r, a) {
function i(t) {
return a.startProgressBar(t), e(function () {
a.stopProgressBar(), n.remove(s.toastId)
}, t, 1)
}
function l() {
s.progressBar = !1, a.stopProgressBar()
}
function c() {
return s.options.closeHtml
}
var u;
if (s.toastClass = s.options.toastClass, s.titleClass = s.options.titleClass, s.messageClass = s.options.messageClass, s.progressBar = s.options.progressBar, c()) {
var p = angular.element(s.options.closeHtml), d = t.get("$compile");
p.addClass("toast-close-button"), p.attr("ng-click", "close()"), d(p)(s), o.prepend(p)
}
s.init = function () {
s.options.timeOut && (u = i(s.options.timeOut)), s.options.onShown && s.options.onShown()
}, o.on("mouseenter", function () {
l(), u && e.cancel(u)
}), s.tapToast = function () {
s.options.tapToDismiss && s.close(!0)
}, s.close = function (t) {
n.remove(s.toastId, t)
}, o.on("mouseleave", function () {
(0 !== s.options.timeOut || 0 !== s.options.extendedTimeOut) && (s.$apply(function () {
s.progressBar = s.options.progressBar
}), u = i(s.options.extendedTimeOut))
})
}
return {
replace: !0, templateUrl: function () {
return s.templates.toast
}, controller: "ToastController", link: o
}
}
angular.module("toastr").directive("toast", t), t.$inject = ["$injector", "$interval", "toastrConfig", "toastr"]
}(), angular.module("toastr").run(["$templateCache", function (t) {
t.put("directives/progressbar/progressbar.html", '<div class="toast-progress"></div>\n'), t.put("directives/toast/toast.html", '<div class="{{toastClass}} {{toastType}}" ng-click="tapToast()">\n <div ng-switch on="allowHtml">\n <div ng-switch-default ng-if="title" class="{{titleClass}}">{{title}}</div>\n <div ng-switch-default class="{{messageClass}}">{{message}}</div>\n <div ng-switch-when="true" ng-if="title" class="{{titleClass}}" ng-bind-html="title"></div>\n <div ng-switch-when="true" class="{{messageClass}}" ng-bind-html="message"></div>\n </div>\n <progress-bar ng-if="progressBar"></progress-bar>\n</div>\n')
}]);
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
var self = this; var self = this;
this.loadRegistries = function() { this.loadRegistries = function () {
$http.get("demo/client/registries") $http.get("demo/client/registries")
.success(function (data) { .success(function (data) {
self.registries = data; self.registries = data;
...@@ -26,43 +26,43 @@ ...@@ -26,43 +26,43 @@
}); });
}; };
this.queryConfig = function() { this.queryConfig = function () {
$http.get("demo/config/" + encodeURIComponent(this.configQuery.configName)) $http.get("demo/config/" + encodeURIComponent(this.configQuery.configName))
.success(function(data) { .success(function (data) {
self.configQuery.configValue = data.value; self.configQuery.configValue = data.value;
}) })
.error(function(data, status) { .error(function (data, status) {
toastr.error((data && data.msg) || 'Load config failed'); toastr.error((data && data.msg) || 'Load config failed');
}); });
}; };
this.queryInjectedConfig = function () { this.queryInjectedConfig = function () {
$http.get("demo/injected/config") $http.get("demo/injected/config")
.success(function(data) { .success(function (data) {
self.injectedConfigValue = data.value; self.injectedConfigValue = data.value;
}) })
.error(function(data, status) { .error(function (data, status) {
toastr.error((data && data.msg) || 'Load injected config failed'); toastr.error((data && data.msg) || 'Load injected config failed');
}); });
}; };
this.refreshConfig = function() { this.refreshConfig = function () {
$http.post("demo/refresh") $http.post("demo/refresh")
.success(function(data) { .success(function (data) {
self.assembleRefreshResult(data); self.assembleRefreshResult(data);
}) })
.error(function(data, status) { .error(function (data, status) {
toastr.error((data && data.msg) || 'Refresh config failed'); toastr.error((data && data.msg) || 'Refresh config failed');
}); });
}; };
this.assembleRefreshResult = function(changedPropertyArray) { this.assembleRefreshResult = function (changedPropertyArray) {
if(!changedPropertyArray || !changedPropertyArray.length) { if (!changedPropertyArray || !changedPropertyArray.length) {
this.refreshResult = NONE; this.refreshResult = NONE;
return; return;
} }
this.refreshResult = _.map(changedPropertyArray, function(propertyChange) { this.refreshResult = _.map(changedPropertyArray, function (propertyChange) {
return propertyChange.propertyName + '(' + propertyChange.changeType + ')'; return propertyChange.propertyName + '(' + propertyChange.changeType + ')';
}); });
}; };
......
...@@ -4,4 +4,95 @@ ...@@ -4,4 +4,95 @@
* Copyright (c) 2015 Wes Cruver * Copyright (c) 2015 Wes Cruver
* License: MIT * License: MIT
*/ */
!function(){"use strict";angular.module("angular-loading-bar",["cfp.loadingBarInterceptor"]),angular.module("chieffancypants.loadingBar",["cfp.loadingBarInterceptor"]),angular.module("cfp.loadingBarInterceptor",["cfp.loadingBar"]).config(["$httpProvider",function(a){var b=["$q","$cacheFactory","$timeout","$rootScope","$log","cfpLoadingBar",function(b,c,d,e,f,g){function h(){d.cancel(j),g.complete(),l=0,k=0}function i(b){var d,e=c.get("$http"),f=a.defaults;!b.cache&&!f.cache||b.cache===!1||"GET"!==b.method&&"JSONP"!==b.method||(d=angular.isObject(b.cache)?b.cache:angular.isObject(f.cache)?f.cache:e);var g=void 0!==d?void 0!==d.get(b.url):!1;return void 0!==b.cached&&g!==b.cached?b.cached:(b.cached=g,g)}var j,k=0,l=0,m=g.latencyThreshold;return{request:function(a){return a.ignoreLoadingBar||i(a)||(e.$broadcast("cfpLoadingBar:loading",{url:a.url}),0===k&&(j=d(function(){g.start()},m)),k++,g.set(l/k)),a},response:function(a){return a&&a.config?(a.config.ignoreLoadingBar||i(a.config)||(l++,e.$broadcast("cfpLoadingBar:loaded",{url:a.config.url,result:a}),l>=k?h():g.set(l/k)),a):(f.error("Broken interceptor detected: Config object not supplied in response:\n https://github.com/chieffancypants/angular-loading-bar/pull/50"),a)},responseError:function(a){return a&&a.config?(a.config.ignoreLoadingBar||i(a.config)||(l++,e.$broadcast("cfpLoadingBar:loaded",{url:a.config.url,result:a}),l>=k?h():g.set(l/k)),b.reject(a)):(f.error("Broken interceptor detected: Config object not supplied in rejection:\n https://github.com/chieffancypants/angular-loading-bar/pull/50"),b.reject(a))}}}];a.interceptors.push(b)}]),angular.module("cfp.loadingBar",[]).provider("cfpLoadingBar",function(){this.autoIncrement=!0,this.includeSpinner=!0,this.includeBar=!0,this.latencyThreshold=100,this.startSize=.02,this.parentSelector="body",this.spinnerTemplate='<div id="loading-bar-spinner"><div class="spinner-icon"></div></div>',this.loadingBarTemplate='<div id="loading-bar"><div class="bar"><div class="peg"></div></div></div>',this.$get=["$injector","$document","$timeout","$rootScope",function(a,b,c,d){function e(){k||(k=a.get("$animate"));var e=b.find(n).eq(0);c.cancel(m),r||(d.$broadcast("cfpLoadingBar:started"),r=!0,v&&k.enter(o,e,angular.element(e[0].lastChild)),u&&k.enter(q,e,angular.element(e[0].lastChild)),f(w))}function f(a){if(r){var b=100*a+"%";p.css("width",b),s=a,t&&(c.cancel(l),l=c(function(){g()},250))}}function g(){if(!(h()>=1)){var a=0,b=h();a=b>=0&&.25>b?(3*Math.random()+3)/100:b>=.25&&.65>b?3*Math.random()/100:b>=.65&&.9>b?2*Math.random()/100:b>=.9&&.99>b?.005:0;var c=h()+a;f(c)}}function h(){return s}function i(){s=0,r=!1}function j(){k||(k=a.get("$animate")),d.$broadcast("cfpLoadingBar:completed"),f(1),c.cancel(m),m=c(function(){var a=k.leave(o,i);a&&a.then&&a.then(i),k.leave(q)},500)}var k,l,m,n=this.parentSelector,o=angular.element(this.loadingBarTemplate),p=o.find("div").eq(0),q=angular.element(this.spinnerTemplate),r=!1,s=0,t=this.autoIncrement,u=this.includeSpinner,v=this.includeBar,w=this.startSize;return{start:e,set:f,status:h,inc:g,complete:j,autoIncrement:this.autoIncrement,includeSpinner:this.includeSpinner,latencyThreshold:this.latencyThreshold,parentSelector:this.parentSelector,startSize:this.startSize}}]})}(); !function () {
\ No newline at end of file "use strict";
angular.module("angular-loading-bar", ["cfp.loadingBarInterceptor"]), angular.module("chieffancypants.loadingBar", ["cfp.loadingBarInterceptor"]), angular.module("cfp.loadingBarInterceptor", ["cfp.loadingBar"]).config(["$httpProvider", function (a) {
var b = ["$q", "$cacheFactory", "$timeout", "$rootScope", "$log", "cfpLoadingBar", function (b, c, d, e, f, g) {
function h() {
d.cancel(j), g.complete(), l = 0, k = 0
}
function i(b) {
var d, e = c.get("$http"), f = a.defaults;
!b.cache && !f.cache || b.cache === !1 || "GET" !== b.method && "JSONP" !== b.method || (d = angular.isObject(b.cache) ? b.cache : angular.isObject(f.cache) ? f.cache : e);
var g = void 0 !== d ? void 0 !== d.get(b.url) : !1;
return void 0 !== b.cached && g !== b.cached ? b.cached : (b.cached = g, g)
}
var j, k = 0, l = 0, m = g.latencyThreshold;
return {
request: function (a) {
return a.ignoreLoadingBar || i(a) || (e.$broadcast("cfpLoadingBar:loading", {url: a.url}), 0 === k && (j = d(function () {
g.start()
}, m)), k++, g.set(l / k)), a
}, response: function (a) {
return a && a.config ? (a.config.ignoreLoadingBar || i(a.config) || (l++, e.$broadcast("cfpLoadingBar:loaded", {
url: a.config.url,
result: a
}), l >= k ? h() : g.set(l / k)), a) : (f.error("Broken interceptor detected: Config object not supplied in response:\n https://github.com/chieffancypants/angular-loading-bar/pull/50"), a)
}, responseError: function (a) {
return a && a.config ? (a.config.ignoreLoadingBar || i(a.config) || (l++, e.$broadcast("cfpLoadingBar:loaded", {
url: a.config.url,
result: a
}), l >= k ? h() : g.set(l / k)), b.reject(a)) : (f.error("Broken interceptor detected: Config object not supplied in rejection:\n https://github.com/chieffancypants/angular-loading-bar/pull/50"), b.reject(a))
}
}
}];
a.interceptors.push(b)
}]), angular.module("cfp.loadingBar", []).provider("cfpLoadingBar", function () {
this.autoIncrement = !0, this.includeSpinner = !0, this.includeBar = !0, this.latencyThreshold = 100, this.startSize = .02, this.parentSelector = "body", this.spinnerTemplate = '<div id="loading-bar-spinner"><div class="spinner-icon"></div></div>', this.loadingBarTemplate = '<div id="loading-bar"><div class="bar"><div class="peg"></div></div></div>', this.$get = ["$injector", "$document", "$timeout", "$rootScope", function (a, b, c, d) {
function e() {
k || (k = a.get("$animate"));
var e = b.find(n).eq(0);
c.cancel(m), r || (d.$broadcast("cfpLoadingBar:started"), r = !0, v && k.enter(o, e, angular.element(e[0].lastChild)), u && k.enter(q, e, angular.element(e[0].lastChild)), f(w))
}
function f(a) {
if (r) {
var b = 100 * a + "%";
p.css("width", b), s = a, t && (c.cancel(l), l = c(function () {
g()
}, 250))
}
}
function g() {
if (!(h() >= 1)) {
var a = 0, b = h();
a = b >= 0 && .25 > b ? (3 * Math.random() + 3) / 100 : b >= .25 && .65 > b ? 3 * Math.random() / 100 : b >= .65 && .9 > b ? 2 * Math.random() / 100 : b >= .9 && .99 > b ? .005 : 0;
var c = h() + a;
f(c)
}
}
function h() {
return s
}
function i() {
s = 0, r = !1
}
function j() {
k || (k = a.get("$animate")), d.$broadcast("cfpLoadingBar:completed"), f(1), c.cancel(m), m = c(function () {
var a = k.leave(o, i);
a && a.then && a.then(i), k.leave(q)
}, 500)
}
var k, l, m, n = this.parentSelector, o = angular.element(this.loadingBarTemplate), p = o.find("div").eq(0), q = angular.element(this.spinnerTemplate), r = !1, s = 0, t = this.autoIncrement, u = this.includeSpinner, v = this.includeBar, w = this.startSize;
return {
start: e,
set: f,
status: h,
inc: g,
complete: j,
autoIncrement: this.autoIncrement,
includeSpinner: this.includeSpinner,
latencyThreshold: this.latencyThreshold,
parentSelector: this.parentSelector,
startSize: this.startSize
}
}]
})
}();
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
.toast-title{font-weight:700}.toast-message{word-wrap:break-word}.toast-message a,.toast-message label{color:#fff}.toast-message a:hover{color:#ccc;text-decoration:none}.toast-close-button{position:relative;right:-.3em;top:-.3em;float:right;font-size:20px;font-weight:700;color:#fff;-webkit-text-shadow:0 1px 0 #fff;text-shadow:0 1px 0 #fff;opacity:.8}.toast-close-button:focus,.toast-close-button:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4}button.toast-close-button{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.toast-top-center{top:0;right:0;width:100%}.toast-bottom-center{bottom:0;right:0;width:100%}.toast-top-full-width{top:0;right:0;width:100%}.toast-bottom-full-width{bottom:0;right:0;width:100%}.toast-top-left{top:12px;left:12px}.toast-top-right{top:12px;right:12px}.toast-bottom-right{right:12px;bottom:12px}.toast-bottom-left{bottom:12px;left:12px}#toast-container{position:fixed;z-index:999999}#toast-container *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}#toast-container>div{position:relative;overflow:hidden;margin:0 0 6px;padding:15px 15px 15px 50px;width:300px;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;background-position:15px center;background-repeat:no-repeat;-moz-box-shadow:0 0 12px #999;-webkit-box-shadow:0 0 12px #999;box-shadow:0 0 12px #999;color:#fff;opacity:.8}#toast-container>:hover{-moz-box-shadow:0 0 12px #000;-webkit-box-shadow:0 0 12px #000;box-shadow:0 0 12px #000;opacity:1;cursor:pointer}#toast-container>.toast-info{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=)!important}#toast-container>.toast-error{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=)!important}#toast-container>.toast-success{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==)!important}#toast-container>.toast-warning{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=)!important}#toast-container.toast-bottom-center>div,#toast-container.toast-top-center>div{width:300px;margin:auto}#toast-container.toast-bottom-full-width>div,#toast-container.toast-top-full-width>div{width:96%;margin:auto}.toast{background-color:#030303}.toast-success{background-color:#51a351}.toast-error{background-color:#bd362f}.toast-info{background-color:#2f96b4}.toast-warning{background-color:#f89406}.toast-progress{position:absolute;left:0;bottom:0;height:4px;background-color:#000;opacity:.4}.toast{opacity:1!important}.toast.ng-enter{opacity:0!important;transition:opacity .3s linear}.toast.ng-enter.ng-enter-active{opacity:1!important}.toast.ng-leave{opacity:1;transition:opacity .3s linear}.toast.ng-leave.ng-leave-active{opacity:0!important}@media all and (max-width:240px){#toast-container>div{padding:8px 8px 8px 50px;width:11em}#toast-container .toast-close-button{right:-.2em;top:-.2em}}@media all and (min-width:241px)and (max-width:480px){#toast-container>div{padding:8px 8px 8px 50px;width:18em}#toast-container .toast-close-button{right:-.2em;top:-.2em}}@media all and (min-width:481px)and (max-width:768px){#toast-container>div{padding:15px 15px 15px 50px;width:25em}} .toast-title {
\ No newline at end of file font-weight: 700
}
.toast-message {
word-wrap: break-word
}
.toast-message a, .toast-message label {
color: #fff
}
.toast-message a:hover {
color: #ccc;
text-decoration: none
}
.toast-close-button {
position: relative;
right: -.3em;
top: -.3em;
float: right;
font-size: 20px;
font-weight: 700;
color: #fff;
-webkit-text-shadow: 0 1px 0 #fff;
text-shadow: 0 1px 0 #fff;
opacity: .8
}
.toast-close-button:focus, .toast-close-button:hover {
color: #000;
text-decoration: none;
cursor: pointer;
opacity: .4
}
button.toast-close-button {
padding: 0;
cursor: pointer;
background: 0 0;
border: 0;
-webkit-appearance: none
}
.toast-top-center {
top: 0;
right: 0;
width: 100%
}
.toast-bottom-center {
bottom: 0;
right: 0;
width: 100%
}
.toast-top-full-width {
top: 0;
right: 0;
width: 100%
}
.toast-bottom-full-width {
bottom: 0;
right: 0;
width: 100%
}
.toast-top-left {
top: 12px;
left: 12px
}
.toast-top-right {
top: 12px;
right: 12px
}
.toast-bottom-right {
right: 12px;
bottom: 12px
}
.toast-bottom-left {
bottom: 12px;
left: 12px
}
#toast-container {
position: fixed;
z-index: 999999
}
#toast-container * {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box
}
#toast-container > div {
position: relative;
overflow: hidden;
margin: 0 0 6px;
padding: 15px 15px 15px 50px;
width: 300px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
background-position: 15px center;
background-repeat: no-repeat;
-moz-box-shadow: 0 0 12px #999;
-webkit-box-shadow: 0 0 12px #999;
box-shadow: 0 0 12px #999;
color: #fff;
opacity: .8
}
#toast-container > :hover {
-moz-box-shadow: 0 0 12px #000;
-webkit-box-shadow: 0 0 12px #000;
box-shadow: 0 0 12px #000;
opacity: 1;
cursor: pointer
}
#toast-container > .toast-info {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=) !important
}
#toast-container > .toast-error {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=) !important
}
#toast-container > .toast-success {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==) !important
}
#toast-container > .toast-warning {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=) !important
}
#toast-container.toast-bottom-center > div, #toast-container.toast-top-center > div {
width: 300px;
margin: auto
}
#toast-container.toast-bottom-full-width > div, #toast-container.toast-top-full-width > div {
width: 96%;
margin: auto
}
.toast {
background-color: #030303
}
.toast-success {
background-color: #51a351
}
.toast-error {
background-color: #bd362f
}
.toast-info {
background-color: #2f96b4
}
.toast-warning {
background-color: #f89406
}
.toast-progress {
position: absolute;
left: 0;
bottom: 0;
height: 4px;
background-color: #000;
opacity: .4
}
.toast {
opacity: 1 !important
}
.toast.ng-enter {
opacity: 0 !important;
transition: opacity .3s linear
}
.toast.ng-enter.ng-enter-active {
opacity: 1 !important
}
.toast.ng-leave {
opacity: 1;
transition: opacity .3s linear
}
.toast.ng-leave.ng-leave-active {
opacity: 0 !important
}
@media all and (max-width: 240px) {
#toast-container > div {
padding: 8px 8px 8px 50px;
width: 11em
}
#toast-container .toast-close-button {
right: -.2em;
top: -.2em
}
}
@media all and (min-width: 241px)and (max-width: 480px) {
#toast-container > div {
padding: 8px 8px 8px 50px;
width: 18em
}
#toast-container .toast-close-button {
right: -.2em;
top: -.2em
}
}
@media all and (min-width: 481px)and (max-width: 768px) {
#toast-container > div {
padding: 15px 15px 15px 50px;
width: 25em
}
}
#loading-bar,#loading-bar-spinner{pointer-events:none;-webkit-pointer-events:none;-webkit-transition:350ms linear all;-moz-transition:350ms linear all;-o-transition:350ms linear all;transition:350ms linear all}#loading-bar-spinner.ng-enter,#loading-bar-spinner.ng-leave.ng-leave-active,#loading-bar.ng-enter,#loading-bar.ng-leave.ng-leave-active{opacity:0}#loading-bar-spinner.ng-enter.ng-enter-active,#loading-bar-spinner.ng-leave,#loading-bar.ng-enter.ng-enter-active,#loading-bar.ng-leave{opacity:1}#loading-bar .bar{-webkit-transition:width 350ms;-moz-transition:width 350ms;-o-transition:width 350ms;transition:width 350ms;background:#29d;position:fixed;z-index:10002;top:0;left:0;width:100%;height:2px;border-bottom-right-radius:1px;border-top-right-radius:1px}#loading-bar .peg{position:absolute;width:70px;right:0;top:0;height:2px;opacity:.45;-moz-box-shadow:#29d 1px 0 6px 1px;-ms-box-shadow:#29d 1px 0 6px 1px;-webkit-box-shadow:#29d 1px 0 6px 1px;box-shadow:#29d 1px 0 6px 1px;-moz-border-radius:100%;-webkit-border-radius:100%;border-radius:100%}#loading-bar-spinner{display:block;position:fixed;z-index:10002;top:10px;left:10px}#loading-bar-spinner .spinner-icon{width:14px;height:14px;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:loading-bar-spinner 400ms linear infinite;-moz-animation:loading-bar-spinner 400ms linear infinite;-ms-animation:loading-bar-spinner 400ms linear infinite;-o-animation:loading-bar-spinner 400ms linear infinite;animation:loading-bar-spinner 400ms linear infinite}@-webkit-keyframes loading-bar-spinner{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-moz-keyframes loading-bar-spinner{0%{-moz-transform:rotate(0);transform:rotate(0)}100%{-moz-transform:rotate(360deg);transform:rotate(360deg)}}@-o-keyframes loading-bar-spinner{0%{-o-transform:rotate(0);transform:rotate(0)}100%{-o-transform:rotate(360deg);transform:rotate(360deg)}}@-ms-keyframes loading-bar-spinner{0%{-ms-transform:rotate(0);transform:rotate(0)}100%{-ms-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes loading-bar-spinner{0%{transform:rotate(0)}100%{transform:rotate(360deg)}} #loading-bar, #loading-bar-spinner {
\ No newline at end of file pointer-events: none;
-webkit-pointer-events: none;
-webkit-transition: 350ms linear all;
-moz-transition: 350ms linear all;
-o-transition: 350ms linear all;
transition: 350ms linear all
}
#loading-bar-spinner.ng-enter, #loading-bar-spinner.ng-leave.ng-leave-active, #loading-bar.ng-enter, #loading-bar.ng-leave.ng-leave-active {
opacity: 0
}
#loading-bar-spinner.ng-enter.ng-enter-active, #loading-bar-spinner.ng-leave, #loading-bar.ng-enter.ng-enter-active, #loading-bar.ng-leave {
opacity: 1
}
#loading-bar .bar {
-webkit-transition: width 350ms;
-moz-transition: width 350ms;
-o-transition: width 350ms;
transition: width 350ms;
background: #29d;
position: fixed;
z-index: 10002;
top: 0;
left: 0;
width: 100%;
height: 2px;
border-bottom-right-radius: 1px;
border-top-right-radius: 1px
}
#loading-bar .peg {
position: absolute;
width: 70px;
right: 0;
top: 0;
height: 2px;
opacity: .45;
-moz-box-shadow: #29d 1px 0 6px 1px;
-ms-box-shadow: #29d 1px 0 6px 1px;
-webkit-box-shadow: #29d 1px 0 6px 1px;
box-shadow: #29d 1px 0 6px 1px;
-moz-border-radius: 100%;
-webkit-border-radius: 100%;
border-radius: 100%
}
#loading-bar-spinner {
display: block;
position: fixed;
z-index: 10002;
top: 10px;
left: 10px
}
#loading-bar-spinner .spinner-icon {
width: 14px;
height: 14px;
border: 2px solid transparent;
border-top-color: #29d;
border-left-color: #29d;
border-radius: 50%;
-webkit-animation: loading-bar-spinner 400ms linear infinite;
-moz-animation: loading-bar-spinner 400ms linear infinite;
-ms-animation: loading-bar-spinner 400ms linear infinite;
-o-animation: loading-bar-spinner 400ms linear infinite;
animation: loading-bar-spinner 400ms linear infinite
}
@-webkit-keyframes loading-bar-spinner {
0% {
-webkit-transform: rotate(0);
transform: rotate(0)
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg)
}
}
@-moz-keyframes loading-bar-spinner {
0% {
-moz-transform: rotate(0);
transform: rotate(0)
}
100% {
-moz-transform: rotate(360deg);
transform: rotate(360deg)
}
}
@-o-keyframes loading-bar-spinner {
0% {
-o-transform: rotate(0);
transform: rotate(0)
}
100% {
-o-transform: rotate(360deg);
transform: rotate(360deg)
}
}
@-ms-keyframes loading-bar-spinner {
0% {
-ms-transform: rotate(0);
transform: rotate(0)
}
100% {
-ms-transform: rotate(360deg);
transform: rotate(360deg)
}
}
@keyframes loading-bar-spinner {
0% {
transform: rotate(0)
}
100% {
transform: rotate(360deg)
}
}
...@@ -44,7 +44,8 @@ ...@@ -44,7 +44,8 @@
<div id="config-value-wrapper" class="clearfix"> <div id="config-value-wrapper" class="clearfix">
<label class="col-sm-2 control-label">Config Value</label> <label class="col-sm-2 control-label">Config Value</label>
<div class="col-sm-3"> <div class="col-sm-3">
<textarea rows="2" cols="38" readonly class="form-control">{{demoCtrl.configQuery.configValue}}</textarea> <textarea rows="2" cols="38" readonly
class="form-control">{{demoCtrl.configQuery.configValue}}</textarea>
</div> </div>
</div> </div>
</div> </div>
......
package com.ctrip.apollo.portal.controller; package com.ctrip.apollo.portal.controller;
import java.util.List; import com.ctrip.apollo.portal.entity.App;
import com.ctrip.apollo.portal.exception.NotFoundException;
import com.ctrip.apollo.portal.service.AppService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
...@@ -11,9 +13,7 @@ import org.springframework.web.bind.annotation.RequestMapping; ...@@ -11,9 +13,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import com.ctrip.apollo.portal.entity.App; import java.util.List;
import com.ctrip.apollo.portal.exception.NotFoundException;
import com.ctrip.apollo.portal.service.AppService;
@RestController @RestController
@RequestMapping("/apps") @RequestMapping("/apps")
......
...@@ -4,6 +4,7 @@ import com.ctrip.apollo.portal.constants.PortalConstants; ...@@ -4,6 +4,7 @@ import com.ctrip.apollo.portal.constants.PortalConstants;
import com.ctrip.apollo.portal.entity.AppConfigVO; import com.ctrip.apollo.portal.entity.AppConfigVO;
import com.ctrip.apollo.portal.exception.NotFoundException; import com.ctrip.apollo.portal.exception.NotFoundException;
import com.ctrip.apollo.portal.service.ConfigService; import com.ctrip.apollo.portal.service.ConfigService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
...@@ -17,7 +18,8 @@ public class ConfigController { ...@@ -17,7 +18,8 @@ public class ConfigController {
private ConfigService configService; private ConfigService configService;
@RequestMapping("/{appId}/{env}/{versionId}") @RequestMapping("/{appId}/{env}/{versionId}")
public AppConfigVO detail(@PathVariable long appId, @PathVariable String env, @PathVariable long versionId) { public AppConfigVO detail(@PathVariable long appId, @PathVariable String env,
@PathVariable long versionId) {
if (appId <= 0) { if (appId <= 0) {
throw new NotFoundException(); throw new NotFoundException();
......
package com.ctrip.apollo.portal.controller; package com.ctrip.apollo.portal.controller;
import static org.springframework.http.HttpStatus.BAD_REQUEST; import com.ctrip.apollo.portal.exception.NotFoundException;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import static org.springframework.http.HttpStatus.NOT_FOUND;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
...@@ -19,7 +11,18 @@ import org.springframework.web.bind.annotation.ControllerAdvice; ...@@ -19,7 +11,18 @@ import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.ResponseStatus;
import com.ctrip.apollo.portal.exception.NotFoundException; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import static org.springframework.http.HttpStatus.NOT_FOUND;
import static org.springframework.http.MediaType.APPLICATION_JSON;
@ControllerAdvice @ControllerAdvice
public class GlobalDefaultExceptionHandler { public class GlobalDefaultExceptionHandler {
...@@ -34,7 +37,8 @@ public class GlobalDefaultExceptionHandler { ...@@ -34,7 +37,8 @@ public class GlobalDefaultExceptionHandler {
} }
private ResponseEntity<Map<String, Object>> handleError(HttpServletRequest request, private ResponseEntity<Map<String, Object>> handleError(HttpServletRequest request,
HttpStatus status, Throwable ex, String message) { HttpStatus status, Throwable ex,
String message) {
ex = resolveError(ex); ex = resolveError(ex);
Map<String, Object> errorAttributes = new LinkedHashMap<>(); Map<String, Object> errorAttributes = new LinkedHashMap<>();
errorAttributes.put("status", status.value()); errorAttributes.put("status", status.value());
...@@ -55,7 +59,8 @@ public class GlobalDefaultExceptionHandler { ...@@ -55,7 +59,8 @@ public class GlobalDefaultExceptionHandler {
@ExceptionHandler(NotFoundException.class) @ExceptionHandler(NotFoundException.class)
@ResponseStatus(value = NOT_FOUND) @ResponseStatus(value = NOT_FOUND)
public void notFound(HttpServletRequest req, NotFoundException ex) {} public void notFound(HttpServletRequest req, NotFoundException ex) {
}
private Throwable resolveError(Throwable ex) { private Throwable resolveError(Throwable ex) {
while (ex instanceof ServletException && ex.getCause() != null) { while (ex instanceof ServletException && ex.getCause() != null) {
......
...@@ -2,6 +2,7 @@ package com.ctrip.apollo.portal.controller; ...@@ -2,6 +2,7 @@ package com.ctrip.apollo.portal.controller;
import com.ctrip.apollo.core.dto.VersionDTO; import com.ctrip.apollo.core.dto.VersionDTO;
import com.ctrip.apollo.portal.service.VersionService; import com.ctrip.apollo.portal.service.VersionService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
...@@ -17,7 +18,7 @@ public class VersionController { ...@@ -17,7 +18,7 @@ public class VersionController {
private VersionService versionService; private VersionService versionService;
@RequestMapping("/{appId}/{env}") @RequestMapping("/{appId}/{env}")
public List<VersionDTO> versions(@PathVariable long appId, @PathVariable String env){ public List<VersionDTO> versions(@PathVariable long appId, @PathVariable String env) {
return versionService.findVersionsByApp(appId, env); return versionService.findVersionsByApp(appId, env);
} }
} }
...@@ -39,16 +39,14 @@ public class AppConfigVO { ...@@ -39,16 +39,14 @@ public class AppConfigVO {
* {b -> D} * {b -> D}
* *
* if client read cluster1 configs will return {a -> A, b -> D, c -> C} * if client read cluster1 configs will return {a -> A, b -> D, c -> C}
*
*
*/ */
private List<OverrideClusterConfig> overrideClusterConfigs; private List<OverrideClusterConfig> overrideClusterConfigs;
public AppConfigVO(){ public AppConfigVO() {
} }
public static AppConfigVO newInstance(long appId, long versionId){ public static AppConfigVO newInstance(long appId, long versionId) {
AppConfigVO instance = new AppConfigVO(); AppConfigVO instance = new AppConfigVO();
instance.setAppId(appId); instance.setAppId(appId);
instance.setVersionId(versionId); instance.setVersionId(versionId);
...@@ -67,7 +65,7 @@ public class AppConfigVO { ...@@ -67,7 +65,7 @@ public class AppConfigVO {
private long appId; private long appId;
private List<ConfigItemDTO> configs; private List<ConfigItemDTO> configs;
public OverrideAppConfig(){ public OverrideAppConfig() {
} }
...@@ -87,8 +85,8 @@ public class AppConfigVO { ...@@ -87,8 +85,8 @@ public class AppConfigVO {
this.configs = configs; this.configs = configs;
} }
public void addConfig(ConfigItemDTO config){ public void addConfig(ConfigItemDTO config) {
if (configs == null){ if (configs == null) {
configs = new LinkedList<>(); configs = new LinkedList<>();
} }
configs.add(config); configs.add(config);
...@@ -101,7 +99,8 @@ public class AppConfigVO { ...@@ -101,7 +99,8 @@ public class AppConfigVO {
private String clusterName; private String clusterName;
private List<ConfigItemDTO> configs; private List<ConfigItemDTO> configs;
public OverrideClusterConfig(){} public OverrideClusterConfig() {
}
public String getClusterName() { public String getClusterName() {
return clusterName; return clusterName;
...@@ -121,8 +120,6 @@ public class AppConfigVO { ...@@ -121,8 +120,6 @@ public class AppConfigVO {
} }
public long getAppId() { public long getAppId() {
return appId; return appId;
} }
......
...@@ -2,7 +2,8 @@ package com.ctrip.apollo.portal.enums; ...@@ -2,7 +2,8 @@ package com.ctrip.apollo.portal.enums;
public enum Env { public enum Env {
DEV("dev"), FWS("fws"), FAT("fat"), UAT("uat"), LPT("lpt"), PROD("prod"), TOOLS("tools"), UN_KNOW(""); DEV("dev"), FWS("fws"), FAT("fat"), UAT("uat"), LPT("lpt"), PROD("prod"), TOOLS("tools"), UN_KNOW(
"");
private String value; private String value;
...@@ -25,7 +26,7 @@ public enum Env { ...@@ -25,7 +26,7 @@ public enum Env {
return PROD; return PROD;
} else if ("tools".equals(env)) { } else if ("tools".equals(env)) {
return TOOLS; return TOOLS;
} else{ } else {
return UN_KNOW; return UN_KNOW;
} }
} }
......
package com.ctrip.apollo.portal.repository; package com.ctrip.apollo.portal.repository;
import com.ctrip.apollo.portal.entity.App;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.PagingAndSortingRepository;
import com.ctrip.apollo.portal.entity.App;
public interface AppRepository extends PagingAndSortingRepository<App, String> { public interface AppRepository extends PagingAndSortingRepository<App, String> {
Page<App> findAll(Pageable pageable); Page<App> findAll(Pageable pageable);
......
package com.ctrip.apollo.portal.repository; package com.ctrip.apollo.portal.repository;
import java.util.List; import com.ctrip.apollo.portal.entity.Privilege;
import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.PagingAndSortingRepository;
import com.ctrip.apollo.portal.entity.Privilege; import java.util.List;
public interface PrivilegeRepository extends PagingAndSortingRepository<Privilege, Long> { public interface PrivilegeRepository extends PagingAndSortingRepository<Privilege, Long> {
......
package com.ctrip.apollo.portal.service; package com.ctrip.apollo.portal.service;
import java.util.Date; import com.ctrip.apollo.portal.entity.App;
import com.ctrip.apollo.portal.repository.AppRepository;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.ctrip.apollo.portal.entity.App; import java.util.Date;
import com.ctrip.apollo.portal.repository.AppRepository;
@Service @Service
public class AppService { public class AppService {
......
...@@ -6,9 +6,6 @@ public interface ConfigService { ...@@ -6,9 +6,6 @@ public interface ConfigService {
/** /**
* load config info by appId and versionId * load config info by appId and versionId
* @param appId
* @param versionId
* @return
*/ */
AppConfigVO loadReleaseConfig(long appId, long versionId); AppConfigVO loadReleaseConfig(long appId, long versionId);
......
package com.ctrip.apollo.portal.service; package com.ctrip.apollo.portal.service;
import java.util.List; import com.ctrip.apollo.portal.entity.Privilege;
import com.ctrip.apollo.portal.exception.NotFoundException;
import com.ctrip.apollo.portal.repository.PrivilegeRepository;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.ctrip.apollo.portal.entity.Privilege; import java.util.List;
import com.ctrip.apollo.portal.exception.NotFoundException;
import com.ctrip.apollo.portal.repository.PrivilegeRepository;
@Service @Service
public class PrivilegeService { public class PrivilegeService {
......
...@@ -2,6 +2,7 @@ package com.ctrip.apollo.portal.service; ...@@ -2,6 +2,7 @@ package com.ctrip.apollo.portal.service;
import com.ctrip.apollo.core.dto.VersionDTO; import com.ctrip.apollo.core.dto.VersionDTO;
import com.ctrip.apollo.portal.RestUtils; import com.ctrip.apollo.portal.RestUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.List; import java.util.List;
...@@ -9,7 +10,7 @@ import java.util.List; ...@@ -9,7 +10,7 @@ import java.util.List;
@Service @Service
public class VersionService { public class VersionService {
public List<VersionDTO> findVersionsByApp(long appId, String env){ public List<VersionDTO> findVersionsByApp(long appId, String env) {
return RestUtils.exchangeInGET("http://localhost:8090/version/app/" + appId, List.class); return RestUtils.exchangeInGET("http://localhost:8090/version/app/" + appId, List.class);
} }
} }
package com.ctrip.apollo.portal.service.impl; package com.ctrip.apollo.portal.service.impl;
import com.google.common.collect.Maps;
import com.ctrip.apollo.core.Constants; import com.ctrip.apollo.core.Constants;
import com.ctrip.apollo.core.dto.*; import com.ctrip.apollo.core.dto.ClusterDTO;
import com.ctrip.apollo.core.dto.ConfigItemDTO;
import com.ctrip.apollo.core.dto.ReleaseSnapshotDTO;
import com.ctrip.apollo.core.dto.VersionDTO;
import com.ctrip.apollo.portal.RestUtils; import com.ctrip.apollo.portal.RestUtils;
import com.ctrip.apollo.portal.constants.PortalConstants; import com.ctrip.apollo.portal.constants.PortalConstants;
import com.ctrip.apollo.portal.entity.AppConfigVO; import com.ctrip.apollo.portal.entity.AppConfigVO;
import com.ctrip.apollo.portal.service.ConfigService; import com.ctrip.apollo.portal.service.ConfigService;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@Service @Service
public class ConfigServiceImpl implements ConfigService { public class ConfigServiceImpl implements ConfigService {
...@@ -57,7 +66,8 @@ public class ConfigServiceImpl implements ConfigService { ...@@ -57,7 +66,8 @@ public class ConfigServiceImpl implements ConfigService {
return version.getReleaseId(); return version.getReleaseId();
} }
private void collectDefaultClusterConfigs(long appId, ReleaseSnapshotDTO snapShot, AppConfigVO appConfigVO) { private void collectDefaultClusterConfigs(long appId, ReleaseSnapshotDTO snapShot,
AppConfigVO appConfigVO) {
Map<Long, List<ConfigItemDTO>> groupedConfigs = Map<Long, List<ConfigItemDTO>> groupedConfigs =
groupConfigsByApp(snapShot.getConfigurations()); groupConfigsByApp(snapShot.getConfigurations());
...@@ -122,7 +132,8 @@ public class ConfigServiceImpl implements ConfigService { ...@@ -122,7 +132,8 @@ public class ConfigServiceImpl implements ConfigService {
return Long.valueOf(key.substring(0, key.indexOf("."))); return Long.valueOf(key.substring(0, key.indexOf(".")));
} }
private void collectSpecialClusterConfigs(long appId, ReleaseSnapshotDTO snapShot, AppConfigVO appConfigVO) { private void collectSpecialClusterConfigs(long appId, ReleaseSnapshotDTO snapShot,
AppConfigVO appConfigVO) {
List<AppConfigVO.OverrideClusterConfig> overrideClusterConfigs = List<AppConfigVO.OverrideClusterConfig> overrideClusterConfigs =
appConfigVO.getOverrideClusterConfigs(); appConfigVO.getOverrideClusterConfigs();
AppConfigVO.OverrideClusterConfig overrideClusterConfig = AppConfigVO.OverrideClusterConfig overrideClusterConfig =
...@@ -189,7 +200,8 @@ public class ConfigServiceImpl implements ConfigService { ...@@ -189,7 +200,8 @@ public class ConfigServiceImpl implements ConfigService {
return groupedClusterConfigs; return groupedClusterConfigs;
} }
private void groupConfigByAppAndEnrichDTO(Map<String, List<ConfigItemDTO>> groupedClusterConfigs, AppConfigVO appConfigVO) { private void groupConfigByAppAndEnrichDTO(Map<String, List<ConfigItemDTO>> groupedClusterConfigs,
AppConfigVO appConfigVO) {
long appId = appConfigVO.getAppId(); long appId = appConfigVO.getAppId();
List<ConfigItemDTO> defaultClusterConfigs = appConfigVO.getDefaultClusterConfigs(); List<ConfigItemDTO> defaultClusterConfigs = appConfigVO.getDefaultClusterConfigs();
...@@ -208,7 +220,8 @@ public class ConfigServiceImpl implements ConfigService { ...@@ -208,7 +220,8 @@ public class ConfigServiceImpl implements ConfigService {
if (Constants.DEFAULT_CLUSTER_NAME.equals(clusterName)) { if (Constants.DEFAULT_CLUSTER_NAME.equals(clusterName)) {
//default cluster configs //default cluster configs
collectDefaultClusterConfigs(appId, clusterConfigs, defaultClusterConfigs, overrideAppConfigs); collectDefaultClusterConfigs(appId, clusterConfigs, defaultClusterConfigs,
overrideAppConfigs);
} else { } else {
//override cluster configs //override cluster configs
collectSpecialClusterConfigs(clusterName, clusterConfigs, overrideClusterConfigs); collectSpecialClusterConfigs(clusterName, clusterConfigs, overrideClusterConfigs);
...@@ -216,7 +229,9 @@ public class ConfigServiceImpl implements ConfigService { ...@@ -216,7 +229,9 @@ public class ConfigServiceImpl implements ConfigService {
} }
} }
private void collectDefaultClusterConfigs(long appId, List<ConfigItemDTO> clusterConfigs, List<ConfigItemDTO> defaultClusterConfigs, List<AppConfigVO.OverrideAppConfig> overrideAppConfigs) { private void collectDefaultClusterConfigs(long appId, List<ConfigItemDTO> clusterConfigs,
List<ConfigItemDTO> defaultClusterConfigs,
List<AppConfigVO.OverrideAppConfig> overrideAppConfigs) {
Map<Long, AppConfigVO.OverrideAppConfig> appIdMapOverrideAppConfig = null; Map<Long, AppConfigVO.OverrideAppConfig> appIdMapOverrideAppConfig = null;
...@@ -244,7 +259,8 @@ public class ConfigServiceImpl implements ConfigService { ...@@ -244,7 +259,8 @@ public class ConfigServiceImpl implements ConfigService {
} }
} }
private void collectSpecialClusterConfigs(String clusterName, List<ConfigItemDTO> clusterConfigs, List<AppConfigVO.OverrideClusterConfig> overrideClusterConfigs) { private void collectSpecialClusterConfigs(String clusterName, List<ConfigItemDTO> clusterConfigs,
List<AppConfigVO.OverrideClusterConfig> overrideClusterConfigs) {
AppConfigVO.OverrideClusterConfig overrideClusterConfig = AppConfigVO.OverrideClusterConfig overrideClusterConfig =
new AppConfigVO.OverrideClusterConfig(); new AppConfigVO.OverrideClusterConfig();
overrideClusterConfig.setClusterName(clusterName); overrideClusterConfig.setClusterName(clusterName);
......
...@@ -10,15 +10,15 @@ create_app_module.controller('CreateAppController', ['$scope', '$window', 'toast ...@@ -10,15 +10,15 @@ create_app_module.controller('CreateAppController', ['$scope', '$window', 'toast
owner: 'le' owner: 'le'
}; };
$scope.save = function(){ $scope.save = function () {
AppService.add($scope.app).then(function(result){ AppService.add($scope.app).then(function (result) {
toastr.success('添加成功!'); toastr.success('添加成功!');
setInterval(function(){ setInterval(function () {
$window.location.href = '/views/app/index.html?#appid=' + result.appId; $window.location.href = '/views/app/index.html?#appid=' + result.appId;
},1000); }, 1000);
},function(result){ }, function (result) {
toastr.error('添加失败!'); toastr.error('添加失败!');
}); });
}; };
}]); }]);
...@@ -4,7 +4,7 @@ application_module.controller("AppPageController", ['$rootScope', '$location', ...@@ -4,7 +4,7 @@ application_module.controller("AppPageController", ['$rootScope', '$location',
$rootScope.appId = $location.$$url.split("=")[1]; $rootScope.appId = $location.$$url.split("=")[1];
if(!$rootScope.appId){ if (!$rootScope.appId) {
$rootScope.appId = 6666; $rootScope.appId = 6666;
} }
......
...@@ -4,7 +4,7 @@ body { ...@@ -4,7 +4,7 @@ body {
padding: 0px !important; padding: 0px !important;
margin: 0px !important; margin: 0px !important;
font-size: 13px; font-size: 13px;
padding-bottom:50px; padding-bottom: 50px;
} }
.container { .container {
......
...@@ -2,8 +2,64 @@ ...@@ -2,8 +2,64 @@
AngularJS v1.4.3 AngularJS v1.4.3
(c) 2010-2015 Google, Inc. http://angularjs.org (c) 2010-2015 Google, Inc. http://angularjs.org
License: MIT License: MIT
*/ */
(function(p,g,l){'use strict';function m(b,a,f){var c=f.baseHref(),k=b[0];return function(b,d,e){var f,h;e=e||{};h=e.expires;f=g.isDefined(e.path)?e.path:c;d===l&&(h="Thu, 01 Jan 1970 00:00:00 GMT",d="");g.isString(h)&&(h=new Date(h));d=encodeURIComponent(b)+"="+encodeURIComponent(d);d=d+(f?";path="+f:"")+(e.domain?";domain="+e.domain:"");d+=h?";expires="+h.toUTCString():"";d+=e.secure?";secure":"";e=d.length+1;4096<e&&a.warn("Cookie '"+b+"' possibly not set or overflowed because it was too large ("+ (function (p, g, l) {
e+" > 4096 bytes)!");k.cookie=d}}g.module("ngCookies",["ng"]).provider("$cookies",[function(){var b=this.defaults={};this.$get=["$$cookieReader","$$cookieWriter",function(a,f){return{get:function(c){return a()[c]},getObject:function(c){return(c=this.get(c))?g.fromJson(c):c},getAll:function(){return a()},put:function(c,a,n){f(c,a,n?g.extend({},b,n):b)},putObject:function(c,b,a){this.put(c,g.toJson(b),a)},remove:function(a,k){f(a,l,k?g.extend({},b,k):b)}}}]}]);g.module("ngCookies").factory("$cookieStore", 'use strict';
["$cookies",function(b){return{get:function(a){return b.getObject(a)},put:function(a,f){b.putObject(a,f)},remove:function(a){b.remove(a)}}}]);m.$inject=["$document","$log","$browser"];g.module("ngCookies").provider("$$cookieWriter",function(){this.$get=m})})(window,window.angular); function m(b, a, f) {
var c = f.baseHref(), k = b[0];
return function (b, d, e) {
var f, h;
e = e || {};
h = e.expires;
f = g.isDefined(e.path) ? e.path : c;
d === l && (h = "Thu, 01 Jan 1970 00:00:00 GMT", d = "");
g.isString(h) && (h = new Date(h));
d = encodeURIComponent(b) + "=" + encodeURIComponent(d);
d = d + (f ? ";path=" + f : "") + (e.domain ? ";domain=" + e.domain : "");
d += h ? ";expires=" + h.toUTCString() : "";
d += e.secure ? ";secure" : "";
e = d.length + 1;
4096 < e && a.warn("Cookie '" + b + "' possibly not set or overflowed because it was too large (" +
e + " > 4096 bytes)!");
k.cookie = d
}
}
g.module("ngCookies", ["ng"]).provider("$cookies", [function () {
var b = this.defaults = {};
this.$get = ["$$cookieReader", "$$cookieWriter", function (a, f) {
return {
get: function (c) {
return a()[c]
}, getObject: function (c) {
return (c = this.get(c)) ? g.fromJson(c) : c
}, getAll: function () {
return a()
}, put: function (c, a, n) {
f(c, a, n ? g.extend({}, b, n) : b)
}, putObject: function (c, b, a) {
this.put(c, g.toJson(b), a)
}, remove: function (a, k) {
f(a, l, k ? g.extend({}, b, k) : b)
}
}
}]
}]);
g.module("ngCookies").factory("$cookieStore",
["$cookies", function (b) {
return {
get: function (a) {
return b.getObject(a)
}, put: function (a, f) {
b.putObject(a, f)
}, remove: function (a) {
b.remove(a)
}
}
}]);
m.$inject = ["$document", "$log", "$browser"];
g.module("ngCookies").provider("$$cookieWriter", function () {
this.$get = m
})
})(window, window.angular);
//# sourceMappingURL=angular-cookies.min.js.map //# sourceMappingURL=angular-cookies.min.js.map
...@@ -2,12 +2,180 @@ ...@@ -2,12 +2,180 @@
AngularJS v1.4.3 AngularJS v1.4.3
(c) 2010-2015 Google, Inc. http://angularjs.org (c) 2010-2015 Google, Inc. http://angularjs.org
License: MIT License: MIT
*/ */
(function(I,d,B){'use strict';function D(f,q){q=q||{};d.forEach(q,function(d,h){delete q[h]});for(var h in f)!f.hasOwnProperty(h)||"$"===h.charAt(0)&&"$"===h.charAt(1)||(q[h]=f[h]);return q}var x=d.$$minErr("$resource"),C=/^(\.[a-zA-Z_$@][0-9a-zA-Z_$@]*)+$/;d.module("ngResource",["ng"]).provider("$resource",function(){var f=this;this.defaults={stripTrailingSlashes:!0,actions:{get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},"delete":{method:"DELETE"}}}; (function (I, d, B) {
this.$get=["$http","$q",function(q,h){function u(d,g){this.template=d;this.defaults=s({},f.defaults,g);this.urlParams={}}function w(y,g,l,m){function c(b,k){var c={};k=s({},g,k);r(k,function(a,k){v(a)&&(a=a());var d;if(a&&a.charAt&&"@"==a.charAt(0)){d=b;var e=a.substr(1);if(null==e||""===e||"hasOwnProperty"===e||!C.test("."+e))throw x("badmember",e);for(var e=e.split("."),n=0,g=e.length;n<g&&d!==B;n++){var h=e[n];d=null!==d?d[h]:B}}else d=a;c[k]=d});return c}function F(b){return b.resource}function e(b){D(b|| 'use strict';
{},this)}var G=new u(y,m);l=s({},f.defaults.actions,l);e.prototype.toJSON=function(){var b=s({},this);delete b.$promise;delete b.$resolved;return b};r(l,function(b,k){var g=/^(POST|PUT|PATCH)$/i.test(b.method);e[k]=function(a,z,m,y){var n={},f,l,A;switch(arguments.length){case 4:A=y,l=m;case 3:case 2:if(v(z)){if(v(a)){l=a;A=z;break}l=z;A=m}else{n=a;f=z;l=m;break}case 1:v(a)?l=a:g?f=a:n=a;break;case 0:break;default:throw x("badargs",arguments.length);}var u=this instanceof e,p=u?f:b.isArray?[]:new e(f), function D(f, q) {
t={},w=b.interceptor&&b.interceptor.response||F,C=b.interceptor&&b.interceptor.responseError||B;r(b,function(b,a){"params"!=a&&"isArray"!=a&&"interceptor"!=a&&(t[a]=H(b))});g&&(t.data=f);G.setUrlParams(t,s({},c(f,b.params||{}),n),b.url);n=q(t).then(function(a){var c=a.data,g=p.$promise;if(c){if(d.isArray(c)!==!!b.isArray)throw x("badcfg",k,b.isArray?"array":"object",d.isArray(c)?"array":"object",t.method,t.url);b.isArray?(p.length=0,r(c,function(a){"object"===typeof a?p.push(new e(a)):p.push(a)})): q = q || {};
(D(c,p),p.$promise=g)}p.$resolved=!0;a.resource=p;return a},function(a){p.$resolved=!0;(A||E)(a);return h.reject(a)});n=n.then(function(a){var b=w(a);(l||E)(b,a.headers);return b},C);return u?n:(p.$promise=n,p.$resolved=!1,p)};e.prototype["$"+k]=function(a,b,c){v(a)&&(c=b,b=a,a={});a=e[k].call(this,a,this,b,c);return a.$promise||a}});e.bind=function(b){return w(y,s({},g,b),l)};return e}var E=d.noop,r=d.forEach,s=d.extend,H=d.copy,v=d.isFunction;u.prototype={setUrlParams:function(f,g,l){var m=this, d.forEach(q, function (d, h) {
c=l||m.template,h,e,q=m.urlParams={};r(c.split(/\W/),function(b){if("hasOwnProperty"===b)throw x("badname");!/^\d+$/.test(b)&&b&&(new RegExp("(^|[^\\\\]):"+b+"(\\W|$)")).test(c)&&(q[b]=!0)});c=c.replace(/\\:/g,":");g=g||{};r(m.urlParams,function(b,k){h=g.hasOwnProperty(k)?g[k]:m.defaults[k];d.isDefined(h)&&null!==h?(e=encodeURIComponent(h).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"%20").replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi, delete q[h]
"+"),c=c.replace(new RegExp(":"+k+"(\\W|$)","g"),function(b,a){return e+a})):c=c.replace(new RegExp("(/?):"+k+"(\\W|$)","g"),function(b,a,c){return"/"==c.charAt(0)?c:a+c})});m.defaults.stripTrailingSlashes&&(c=c.replace(/\/+$/,"")||"/");c=c.replace(/\/\.(?=\w+($|\?))/,".");f.url=c.replace(/\/\\\./,"/.");r(g,function(b,c){m.urlParams[c]||(f.params=f.params||{},f.params[c]=b)})}};return w}]})})(window,window.angular); });
for (var h in f)!f.hasOwnProperty(h) || "$" === h.charAt(0) && "$" === h.charAt(1) || (q[h] = f[h]);
return q
}
var x = d.$$minErr("$resource"), C = /^(\.[a-zA-Z_$@][0-9a-zA-Z_$@]*)+$/;
d.module("ngResource", ["ng"]).provider("$resource", function () {
var f = this;
this.defaults = {
stripTrailingSlashes: !0,
actions: {
get: {method: "GET"},
save: {method: "POST"},
query: {method: "GET", isArray: !0},
remove: {method: "DELETE"},
"delete": {method: "DELETE"}
}
};
this.$get = ["$http", "$q", function (q, h) {
function u(d, g) {
this.template = d;
this.defaults = s({}, f.defaults, g);
this.urlParams = {}
}
function w(y, g, l, m) {
function c(b, k) {
var c = {};
k = s({}, g, k);
r(k, function (a, k) {
v(a) && (a = a());
var d;
if (a && a.charAt && "@" == a.charAt(0)) {
d = b;
var e = a.substr(1);
if (null == e || "" === e || "hasOwnProperty" === e || !C.test("." + e))throw x("badmember", e);
for (var e = e.split("."), n = 0, g = e.length; n < g && d !== B; n++) {
var h = e[n];
d = null !== d ? d[h] : B
}
} else d = a;
c[k] = d
});
return c
}
function F(b) {
return b.resource
}
function e(b) {
D(b ||
{}, this)
}
var G = new u(y, m);
l = s({}, f.defaults.actions, l);
e.prototype.toJSON = function () {
var b = s({}, this);
delete b.$promise;
delete b.$resolved;
return b
};
r(l, function (b, k) {
var g = /^(POST|PUT|PATCH)$/i.test(b.method);
e[k] = function (a, z, m, y) {
var n = {}, f, l, A;
switch (arguments.length) {
case 4:
A = y, l = m;
case 3:
case 2:
if (v(z)) {
if (v(a)) {
l = a;
A = z;
break
}
l = z;
A = m
} else {
n = a;
f = z;
l = m;
break
}
case 1:
v(a) ? l = a : g ? f = a : n = a;
break;
case 0:
break;
default:
throw x("badargs", arguments.length);
}
var u = this instanceof e, p = u ? f : b.isArray ? [] : new e(f),
t = {}, w = b.interceptor && b.interceptor.response || F, C = b.interceptor && b.interceptor.responseError || B;
r(b, function (b, a) {
"params" != a && "isArray" != a && "interceptor" != a && (t[a] = H(b))
});
g && (t.data = f);
G.setUrlParams(t, s({}, c(f, b.params || {}), n), b.url);
n = q(t).then(function (a) {
var c = a.data, g = p.$promise;
if (c) {
if (d.isArray(c) !== !!b.isArray)throw x("badcfg", k, b.isArray ? "array" : "object", d.isArray(c) ? "array" : "object", t.method, t.url);
b.isArray ? (p.length = 0, r(c, function (a) {
"object" === typeof a ? p.push(new e(a)) : p.push(a)
})) :
(D(c, p), p.$promise = g)
}
p.$resolved = !0;
a.resource = p;
return a
}, function (a) {
p.$resolved = !0;
(A || E)(a);
return h.reject(a)
});
n = n.then(function (a) {
var b = w(a);
(l || E)(b, a.headers);
return b
}, C);
return u ? n : (p.$promise = n, p.$resolved = !1, p)
};
e.prototype["$" + k] = function (a, b, c) {
v(a) && (c = b, b = a, a = {});
a = e[k].call(this, a, this, b, c);
return a.$promise || a
}
});
e.bind = function (b) {
return w(y, s({}, g, b), l)
};
return e
}
var E = d.noop, r = d.forEach, s = d.extend, H = d.copy, v = d.isFunction;
u.prototype = {
setUrlParams: function (f, g, l) {
var m = this,
c = l || m.template, h, e, q = m.urlParams = {};
r(c.split(/\W/), function (b) {
if ("hasOwnProperty" === b)throw x("badname");
!/^\d+$/.test(b) && b && (new RegExp("(^|[^\\\\]):" + b + "(\\W|$)")).test(c) && (q[b] = !0)
});
c = c.replace(/\\:/g, ":");
g = g || {};
r(m.urlParams, function (b, k) {
h = g.hasOwnProperty(k) ? g[k] : m.defaults[k];
d.isDefined(h) && null !== h ? (e = encodeURIComponent(h).replace(/%40/gi, "@").replace(/%3A/gi, ":").replace(/%24/g, "$").replace(/%2C/gi, ",").replace(/%20/g, "%20").replace(/%26/gi, "&").replace(/%3D/gi, "=").replace(/%2B/gi,
"+"), c = c.replace(new RegExp(":" + k + "(\\W|$)", "g"), function (b, a) {
return e + a
})) : c = c.replace(new RegExp("(/?):" + k + "(\\W|$)", "g"), function (b, a, c) {
return "/" == c.charAt(0) ? c : a + c
})
});
m.defaults.stripTrailingSlashes && (c = c.replace(/\/+$/, "") || "/");
c = c.replace(/\/\.(?=\w+($|\?))/, ".");
f.url = c.replace(/\/\\\./, "/.");
r(g, function (b, c) {
m.urlParams[c] || (f.params = f.params || {}, f.params[c] = b)
})
}
};
return w
}]
})
})(window, window.angular);
//# sourceMappingURL=angular-resource.min.js.map //# sourceMappingURL=angular-resource.min.js.map
...@@ -2,14 +2,180 @@ ...@@ -2,14 +2,180 @@
AngularJS v1.4.3 AngularJS v1.4.3
(c) 2010-2015 Google, Inc. http://angularjs.org (c) 2010-2015 Google, Inc. http://angularjs.org
License: MIT License: MIT
*/ */
(function(p,c,C){'use strict';function v(r,h,g){return{restrict:"ECA",terminal:!0,priority:400,transclude:"element",link:function(a,f,b,d,y){function z(){k&&(g.cancel(k),k=null);l&&(l.$destroy(),l=null);m&&(k=g.leave(m),k.then(function(){k=null}),m=null)}function x(){var b=r.current&&r.current.locals;if(c.isDefined(b&&b.$template)){var b=a.$new(),d=r.current;m=y(b,function(b){g.enter(b,null,m||f).then(function(){!c.isDefined(t)||t&&!a.$eval(t)||h()});z()});l=d.scope=b;l.$emit("$viewContentLoaded"); (function (p, c, C) {
l.$eval(w)}else z()}var l,m,k,t=b.autoscroll,w=b.onload||"";a.$on("$routeChangeSuccess",x);x()}}}function A(c,h,g){return{restrict:"ECA",priority:-400,link:function(a,f){var b=g.current,d=b.locals;f.html(d.$template);var y=c(f.contents());b.controller&&(d.$scope=a,d=h(b.controller,d),b.controllerAs&&(a[b.controllerAs]=d),f.data("$ngControllerController",d),f.children().data("$ngControllerController",d));y(a)}}}p=c.module("ngRoute",["ng"]).provider("$route",function(){function r(a,f){return c.extend(Object.create(a), 'use strict';
f)}function h(a,c){var b=c.caseInsensitiveMatch,d={originalPath:a,regexp:a},g=d.keys=[];a=a.replace(/([().])/g,"\\$1").replace(/(\/)?:(\w+)([\?\*])?/g,function(a,c,b,d){a="?"===d?d:null;d="*"===d?d:null;g.push({name:b,optional:!!a});c=c||"";return""+(a?"":c)+"(?:"+(a?c:"")+(d&&"(.+?)"||"([^/]+)")+(a||"")+")"+(a||"")}).replace(/([\/$\*])/g,"\\$1");d.regexp=new RegExp("^"+a+"$",b?"i":"");return d}var g={};this.when=function(a,f){var b=c.copy(f);c.isUndefined(b.reloadOnSearch)&&(b.reloadOnSearch=!0); function v(r, h, g) {
c.isUndefined(b.caseInsensitiveMatch)&&(b.caseInsensitiveMatch=this.caseInsensitiveMatch);g[a]=c.extend(b,a&&h(a,b));if(a){var d="/"==a[a.length-1]?a.substr(0,a.length-1):a+"/";g[d]=c.extend({redirectTo:a},h(d,b))}return this};this.caseInsensitiveMatch=!1;this.otherwise=function(a){"string"===typeof a&&(a={redirectTo:a});this.when(null,a);return this};this.$get=["$rootScope","$location","$routeParams","$q","$injector","$templateRequest","$sce",function(a,f,b,d,h,p,x){function l(b){var e=s.current; return {
(v=(n=k())&&e&&n.$$route===e.$$route&&c.equals(n.pathParams,e.pathParams)&&!n.reloadOnSearch&&!w)||!e&&!n||a.$broadcast("$routeChangeStart",n,e).defaultPrevented&&b&&b.preventDefault()}function m(){var u=s.current,e=n;if(v)u.params=e.params,c.copy(u.params,b),a.$broadcast("$routeUpdate",u);else if(e||u)w=!1,(s.current=e)&&e.redirectTo&&(c.isString(e.redirectTo)?f.path(t(e.redirectTo,e.params)).search(e.params).replace():f.url(e.redirectTo(e.pathParams,f.path(),f.search())).replace()),d.when(e).then(function(){if(e){var a= restrict: "ECA", terminal: !0, priority: 400, transclude: "element", link: function (a, f, b, d, y) {
c.extend({},e.resolve),b,f;c.forEach(a,function(b,e){a[e]=c.isString(b)?h.get(b):h.invoke(b,null,null,e)});c.isDefined(b=e.template)?c.isFunction(b)&&(b=b(e.params)):c.isDefined(f=e.templateUrl)&&(c.isFunction(f)&&(f=f(e.params)),c.isDefined(f)&&(e.loadedTemplateUrl=x.valueOf(f),b=p(f)));c.isDefined(b)&&(a.$template=b);return d.all(a)}}).then(function(f){e==s.current&&(e&&(e.locals=f,c.copy(e.params,b)),a.$broadcast("$routeChangeSuccess",e,u))},function(b){e==s.current&&a.$broadcast("$routeChangeError", function z() {
e,u,b)})}function k(){var a,b;c.forEach(g,function(d,g){var q;if(q=!b){var h=f.path();q=d.keys;var l={};if(d.regexp)if(h=d.regexp.exec(h)){for(var k=1,m=h.length;k<m;++k){var n=q[k-1],p=h[k];n&&p&&(l[n.name]=p)}q=l}else q=null;else q=null;q=a=q}q&&(b=r(d,{params:c.extend({},f.search(),a),pathParams:a}),b.$$route=d)});return b||g[null]&&r(g[null],{params:{},pathParams:{}})}function t(a,b){var d=[];c.forEach((a||"").split(":"),function(a,c){if(0===c)d.push(a);else{var f=a.match(/(\w+)(?:[?*])?(.*)/), k && (g.cancel(k), k = null);
g=f[1];d.push(b[g]);d.push(f[2]||"");delete b[g]}});return d.join("")}var w=!1,n,v,s={routes:g,reload:function(){w=!0;a.$evalAsync(function(){l();m()})},updateParams:function(a){if(this.current&&this.current.$$route)a=c.extend({},this.current.params,a),f.path(t(this.current.$$route.originalPath,a)),f.search(a);else throw B("norout");}};a.$on("$locationChangeStart",l);a.$on("$locationChangeSuccess",m);return s}]});var B=c.$$minErr("ngRoute");p.provider("$routeParams",function(){this.$get=function(){return{}}}); l && (l.$destroy(), l = null);
p.directive("ngView",v);p.directive("ngView",A);v.$inject=["$route","$anchorScroll","$animate"];A.$inject=["$compile","$controller","$route"]})(window,window.angular); m && (k = g.leave(m), k.then(function () {
k = null
}), m = null)
}
function x() {
var b = r.current && r.current.locals;
if (c.isDefined(b && b.$template)) {
var b = a.$new(), d = r.current;
m = y(b, function (b) {
g.enter(b, null, m || f).then(function () {
!c.isDefined(t) || t && !a.$eval(t) || h()
});
z()
});
l = d.scope = b;
l.$emit("$viewContentLoaded");
l.$eval(w)
} else z()
}
var l, m, k, t = b.autoscroll, w = b.onload || "";
a.$on("$routeChangeSuccess", x);
x()
}
}
}
function A(c, h, g) {
return {
restrict: "ECA", priority: -400, link: function (a, f) {
var b = g.current, d = b.locals;
f.html(d.$template);
var y = c(f.contents());
b.controller && (d.$scope = a, d = h(b.controller, d), b.controllerAs && (a[b.controllerAs] = d), f.data("$ngControllerController", d), f.children().data("$ngControllerController", d));
y(a)
}
}
}
p = c.module("ngRoute", ["ng"]).provider("$route", function () {
function r(a, f) {
return c.extend(Object.create(a),
f)
}
function h(a, c) {
var b = c.caseInsensitiveMatch, d = {originalPath: a, regexp: a}, g = d.keys = [];
a = a.replace(/([().])/g, "\\$1").replace(/(\/)?:(\w+)([\?\*])?/g, function (a, c, b, d) {
a = "?" === d ? d : null;
d = "*" === d ? d : null;
g.push({name: b, optional: !!a});
c = c || "";
return "" + (a ? "" : c) + "(?:" + (a ? c : "") + (d && "(.+?)" || "([^/]+)") + (a || "") + ")" + (a || "")
}).replace(/([\/$\*])/g, "\\$1");
d.regexp = new RegExp("^" + a + "$", b ? "i" : "");
return d
}
var g = {};
this.when = function (a, f) {
var b = c.copy(f);
c.isUndefined(b.reloadOnSearch) && (b.reloadOnSearch = !0);
c.isUndefined(b.caseInsensitiveMatch) && (b.caseInsensitiveMatch = this.caseInsensitiveMatch);
g[a] = c.extend(b, a && h(a, b));
if (a) {
var d = "/" == a[a.length - 1] ? a.substr(0, a.length - 1) : a + "/";
g[d] = c.extend({redirectTo: a}, h(d, b))
}
return this
};
this.caseInsensitiveMatch = !1;
this.otherwise = function (a) {
"string" === typeof a && (a = {redirectTo: a});
this.when(null, a);
return this
};
this.$get = ["$rootScope", "$location", "$routeParams", "$q", "$injector", "$templateRequest", "$sce", function (a, f, b, d, h, p, x) {
function l(b) {
var e = s.current;
(v = (n = k()) && e && n.$$route === e.$$route && c.equals(n.pathParams, e.pathParams) && !n.reloadOnSearch && !w) || !e && !n || a.$broadcast("$routeChangeStart", n, e).defaultPrevented && b && b.preventDefault()
}
function m() {
var u = s.current, e = n;
if (v)u.params = e.params, c.copy(u.params, b), a.$broadcast("$routeUpdate", u); else if (e || u)w = !1, (s.current = e) && e.redirectTo && (c.isString(e.redirectTo) ? f.path(t(e.redirectTo, e.params)).search(e.params).replace() : f.url(e.redirectTo(e.pathParams, f.path(), f.search())).replace()), d.when(e).then(function () {
if (e) {
var a =
c.extend({}, e.resolve), b, f;
c.forEach(a, function (b, e) {
a[e] = c.isString(b) ? h.get(b) : h.invoke(b, null, null, e)
});
c.isDefined(b = e.template) ? c.isFunction(b) && (b = b(e.params)) : c.isDefined(f = e.templateUrl) && (c.isFunction(f) && (f = f(e.params)), c.isDefined(f) && (e.loadedTemplateUrl = x.valueOf(f), b = p(f)));
c.isDefined(b) && (a.$template = b);
return d.all(a)
}
}).then(function (f) {
e == s.current && (e && (e.locals = f, c.copy(e.params, b)), a.$broadcast("$routeChangeSuccess", e, u))
}, function (b) {
e == s.current && a.$broadcast("$routeChangeError",
e, u, b)
})
}
function k() {
var a, b;
c.forEach(g, function (d, g) {
var q;
if (q = !b) {
var h = f.path();
q = d.keys;
var l = {};
if (d.regexp)if (h = d.regexp.exec(h)) {
for (var k = 1, m = h.length; k < m; ++k) {
var n = q[k - 1], p = h[k];
n && p && (l[n.name] = p)
}
q = l
} else q = null; else q = null;
q = a = q
}
q && (b = r(d, {params: c.extend({}, f.search(), a), pathParams: a}), b.$$route = d)
});
return b || g[null] && r(g[null], {params: {}, pathParams: {}})
}
function t(a, b) {
var d = [];
c.forEach((a || "").split(":"), function (a, c) {
if (0 === c)d.push(a); else {
var f = a.match(/(\w+)(?:[?*])?(.*)/),
g = f[1];
d.push(b[g]);
d.push(f[2] || "");
delete b[g]
}
});
return d.join("")
}
var w = !1, n, v, s = {
routes: g, reload: function () {
w = !0;
a.$evalAsync(function () {
l();
m()
})
}, updateParams: function (a) {
if (this.current && this.current.$$route)a = c.extend({}, this.current.params, a), f.path(t(this.current.$$route.originalPath, a)), f.search(a); else throw B("norout");
}
};
a.$on("$locationChangeStart", l);
a.$on("$locationChangeSuccess", m);
return s
}]
});
var B = c.$$minErr("ngRoute");
p.provider("$routeParams", function () {
this.$get = function () {
return {}
}
});
p.directive("ngView", v);
p.directive("ngView", A);
v.$inject = ["$route", "$anchorScroll", "$animate"];
A.$inject = ["$compile", "$controller", "$route"]
})(window, window.angular);
//# sourceMappingURL=angular-route.min.js.map //# sourceMappingURL=angular-route.min.js.map
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -5,4 +5,29 @@ ...@@ -5,4 +5,29 @@
* @author Olivier Louvignes <olivier@mg-crea.com> (https://github.com/mgcrea) * @author Olivier Louvignes <olivier@mg-crea.com> (https://github.com/mgcrea)
* @license MIT License, http://www.opensource.org/licenses/MIT * @license MIT License, http://www.opensource.org/licenses/MIT
*/ */
!function(t,e,n){'use strict';angular.module('mgcrea.ngStrap.alert').run(['$templateCache',function(t){t.put('alert/alert.tpl.html','<div class="alert" ng-class="[type ? \'alert-\' + type : null]"><button type="button" class="close" ng-if="dismissable" ng-click="$hide()">&times;</button> <strong ng-bind="title"></strong>&nbsp;<span ng-bind-html="content"></span></div>')}]),angular.module('mgcrea.ngStrap.aside').run(['$templateCache',function(t){t.put('aside/aside.tpl.html','<div class="aside" tabindex="-1" role="dialog"><div class="aside-dialog"><div class="aside-content"><div class="aside-header" ng-show="title"><button type="button" class="close" ng-click="$hide()">&times;</button><h4 class="aside-title" ng-bind="title"></h4></div><div class="aside-body" ng-bind="content"></div><div class="aside-footer"><button type="button" class="btn btn-default" ng-click="$hide()">Close</button></div></div></div></div>')}]),angular.module('mgcrea.ngStrap.datepicker').run(['$templateCache',function(t){t.put('datepicker/datepicker.tpl.html','<div class="dropdown-menu datepicker" ng-class="\'datepicker-mode-\' + $mode" style="max-width: 320px"><table style="table-layout: fixed; height: 100%; width: 100%"><thead><tr class="text-center"><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$selectPane(-1)"><i class="{{$iconLeft}}"></i></button></th><th colspan="{{ rows[0].length - 2 }}"><button tabindex="-1" type="button" class="btn btn-default btn-block text-strong" ng-click="$toggleMode()"><strong style="text-transform: capitalize" ng-bind="title"></strong></button></th><th><button tabindex="-1" type="button" class="btn btn-default pull-right" ng-click="$selectPane(+1)"><i class="{{$iconRight}}"></i></button></th></tr><tr ng-show="showLabels" ng-bind-html="labels"></tr></thead><tbody><tr ng-repeat="(i, row) in rows" height="{{ 100 / rows.length }}%"><td class="text-center" ng-repeat="(j, el) in row"><button tabindex="-1" type="button" class="btn btn-default" style="width: 100%" ng-class="{\'btn-primary\': el.selected, \'btn-info btn-today\': el.isToday && !el.selected}" ng-click="$select(el.date)" ng-disabled="el.disabled"><span ng-class="{\'text-muted\': el.muted}" ng-bind="el.label"></span></button></td></tr></tbody></table></div>')}]),angular.module('mgcrea.ngStrap.dropdown').run(['$templateCache',function(t){t.put('dropdown/dropdown.tpl.html','<ul tabindex="-1" class="dropdown-menu" role="menu"><li role="presentation" ng-class="{divider: item.divider}" ng-repeat="item in content"><a role="menuitem" tabindex="-1" ng-href="{{item.href}}" ng-if="!item.divider && item.href" target="{{item.target || \'\'}}" ng-bind="item.text"></a> <a role="menuitem" tabindex="-1" href="javascript:void(0)" ng-if="!item.divider && item.click" ng-click="$eval(item.click);$hide()" ng-bind="item.text"></a></li></ul>')}]),angular.module('mgcrea.ngStrap.modal').run(['$templateCache',function(t){t.put('modal/modal.tpl.html','<div class="modal" tabindex="-1" role="dialog" aria-hidden="true"><div class="modal-dialog"><div class="modal-content"><div class="modal-header" ng-show="title"><button type="button" class="close" aria-label="Close" ng-click="$hide()"><span aria-hidden="true">&times;</span></button><h4 class="modal-title" ng-bind="title"></h4></div><div class="modal-body" ng-bind="content"></div><div class="modal-footer"><button type="button" class="btn btn-default" ng-click="$hide()">Close</button></div></div></div></div>')}]),angular.module('mgcrea.ngStrap.popover').run(['$templateCache',function(t){t.put('popover/popover.tpl.html','<div class="popover"><div class="arrow"></div><h3 class="popover-title" ng-bind="title" ng-show="title"></h3><div class="popover-content" ng-bind="content"></div></div>')}]),angular.module('mgcrea.ngStrap.select').run(['$templateCache',function(t){t.put('select/select.tpl.html','<ul tabindex="-1" class="select dropdown-menu" ng-show="$isVisible()" role="select"><li ng-if="$showAllNoneButtons"><div class="btn-group" style="margin-bottom: 5px; margin-left: 5px"><button type="button" class="btn btn-default btn-xs" ng-click="$selectAll()">{{$allText}}</button> <button type="button" class="btn btn-default btn-xs" ng-click="$selectNone()">{{$noneText}}</button></div></li><li role="presentation" ng-repeat="match in $matches" ng-class="{active: $isActive($index)}"><a style="cursor: default" role="menuitem" tabindex="-1" ng-click="$select($index, $event)"><i class="{{$iconCheckmark}} pull-right" ng-if="$isMultiple && $isActive($index)"></i> <span ng-bind="match.label"></span></a></li></ul>')}]),angular.module('mgcrea.ngStrap.timepicker').run(['$templateCache',function(t){t.put('timepicker/timepicker.tpl.html','<div class="dropdown-menu timepicker" style="min-width: 0px;width: auto"><table height="100%"><thead><tr class="text-center"><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$arrowAction(-1, 0)"><i class="{{ $iconUp }}"></i></button></th><th>&nbsp;</th><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$arrowAction(-1, 1)"><i class="{{ $iconUp }}"></i></button></th><th>&nbsp;</th><th><button ng-if="showSeconds" tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$arrowAction(-1, 2)"><i class="{{ $iconUp }}"></i></button></th></tr></thead><tbody><tr ng-repeat="(i, row) in rows"><td class="text-center"><button tabindex="-1" style="width: 100%" type="button" class="btn btn-default" ng-class="{\'btn-primary\': row[0].selected}" ng-click="$select(row[0].date, 0)" ng-disabled="row[0].disabled"><span ng-class="{\'text-muted\': row[0].muted}" ng-bind="row[0].label"></span></button></td><td><span ng-bind="i == midIndex ? timeSeparator : \' \'"></span></td><td class="text-center"><button tabindex="-1" ng-if="row[1].date" style="width: 100%" type="button" class="btn btn-default" ng-class="{\'btn-primary\': row[1].selected}" ng-click="$select(row[1].date, 1)" ng-disabled="row[1].disabled"><span ng-class="{\'text-muted\': row[1].muted}" ng-bind="row[1].label"></span></button></td><td><span ng-bind="i == midIndex ? timeSeparator : \' \'"></span></td><td class="text-center"><button tabindex="-1" ng-if="showSeconds && row[2].date" style="width: 100%" type="button" class="btn btn-default" ng-class="{\'btn-primary\': row[2].selected}" ng-click="$select(row[2].date, 2)" ng-disabled="row[2].disabled"><span ng-class="{\'text-muted\': row[2].muted}" ng-bind="row[2].label"></span></button></td><td ng-if="showAM">&nbsp;</td><td ng-if="showAM"><button tabindex="-1" ng-show="i == midIndex - !isAM * 1" style="width: 100%" type="button" ng-class="{\'btn-primary\': !!isAM}" class="btn btn-default" ng-click="$switchMeridian()" ng-disabled="el.disabled">AM</button> <button tabindex="-1" ng-show="i == midIndex + 1 - !isAM * 1" style="width: 100%" type="button" ng-class="{\'btn-primary\': !isAM}" class="btn btn-default" ng-click="$switchMeridian()" ng-disabled="el.disabled">PM</button></td></tr></tbody><tfoot><tr class="text-center"><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$arrowAction(1, 0)"><i class="{{ $iconDown }}"></i></button></th><th>&nbsp;</th><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$arrowAction(1, 1)"><i class="{{ $iconDown }}"></i></button></th><th>&nbsp;</th><th><button ng-if="showSeconds" tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$arrowAction(1, 2)"><i class="{{ $iconDown }}"></i></button></th></tr></tfoot></table></div>')}]),angular.module('mgcrea.ngStrap.tab').run(['$templateCache',function(t){t.put('tab/tab.tpl.html','<ul class="nav" ng-class="$navClass" role="tablist"><li role="presentation" ng-repeat="$pane in $panes track by $index" ng-class="[ $index == $panes.$active ? $activeClass : \'\', $pane.disabled ? \'disabled\' : \'\' ]"><a role="tab" data-toggle="tab" ng-click="!$pane.disabled && $setActive($index)" data-index="{{ $index }}" ng-bind-html="$pane.title" aria-controls="$pane.title"></a></li></ul><div ng-transclude class="tab-content"></div>')}]),angular.module('mgcrea.ngStrap.tooltip').run(['$templateCache',function(t){t.put('tooltip/tooltip.tpl.html','<div class="tooltip in" ng-show="title"><div class="tooltip-arrow"></div><div class="tooltip-inner" ng-bind="title"></div></div>')}]),angular.module('mgcrea.ngStrap.typeahead').run(['$templateCache',function(t){t.put('typeahead/typeahead.tpl.html','<ul tabindex="-1" class="typeahead dropdown-menu" ng-show="$isVisible()" role="select"><li role="presentation" ng-repeat="match in $matches" ng-class="{active: $index == $activeIndex}"><a role="menuitem" tabindex="-1" ng-click="$select($index, $event)" ng-bind="match.label"></a></li></ul>')}])}(window,document); !function (t, e, n) {
\ No newline at end of file 'use strict';
angular.module('mgcrea.ngStrap.alert').run(['$templateCache', function (t) {
t.put('alert/alert.tpl.html', '<div class="alert" ng-class="[type ? \'alert-\' + type : null]"><button type="button" class="close" ng-if="dismissable" ng-click="$hide()">&times;</button> <strong ng-bind="title"></strong>&nbsp;<span ng-bind-html="content"></span></div>')
}]), angular.module('mgcrea.ngStrap.aside').run(['$templateCache', function (t) {
t.put('aside/aside.tpl.html', '<div class="aside" tabindex="-1" role="dialog"><div class="aside-dialog"><div class="aside-content"><div class="aside-header" ng-show="title"><button type="button" class="close" ng-click="$hide()">&times;</button><h4 class="aside-title" ng-bind="title"></h4></div><div class="aside-body" ng-bind="content"></div><div class="aside-footer"><button type="button" class="btn btn-default" ng-click="$hide()">Close</button></div></div></div></div>')
}]), angular.module('mgcrea.ngStrap.datepicker').run(['$templateCache', function (t) {
t.put('datepicker/datepicker.tpl.html', '<div class="dropdown-menu datepicker" ng-class="\'datepicker-mode-\' + $mode" style="max-width: 320px"><table style="table-layout: fixed; height: 100%; width: 100%"><thead><tr class="text-center"><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$selectPane(-1)"><i class="{{$iconLeft}}"></i></button></th><th colspan="{{ rows[0].length - 2 }}"><button tabindex="-1" type="button" class="btn btn-default btn-block text-strong" ng-click="$toggleMode()"><strong style="text-transform: capitalize" ng-bind="title"></strong></button></th><th><button tabindex="-1" type="button" class="btn btn-default pull-right" ng-click="$selectPane(+1)"><i class="{{$iconRight}}"></i></button></th></tr><tr ng-show="showLabels" ng-bind-html="labels"></tr></thead><tbody><tr ng-repeat="(i, row) in rows" height="{{ 100 / rows.length }}%"><td class="text-center" ng-repeat="(j, el) in row"><button tabindex="-1" type="button" class="btn btn-default" style="width: 100%" ng-class="{\'btn-primary\': el.selected, \'btn-info btn-today\': el.isToday && !el.selected}" ng-click="$select(el.date)" ng-disabled="el.disabled"><span ng-class="{\'text-muted\': el.muted}" ng-bind="el.label"></span></button></td></tr></tbody></table></div>')
}]), angular.module('mgcrea.ngStrap.dropdown').run(['$templateCache', function (t) {
t.put('dropdown/dropdown.tpl.html', '<ul tabindex="-1" class="dropdown-menu" role="menu"><li role="presentation" ng-class="{divider: item.divider}" ng-repeat="item in content"><a role="menuitem" tabindex="-1" ng-href="{{item.href}}" ng-if="!item.divider && item.href" target="{{item.target || \'\'}}" ng-bind="item.text"></a> <a role="menuitem" tabindex="-1" href="javascript:void(0)" ng-if="!item.divider && item.click" ng-click="$eval(item.click);$hide()" ng-bind="item.text"></a></li></ul>')
}]), angular.module('mgcrea.ngStrap.modal').run(['$templateCache', function (t) {
t.put('modal/modal.tpl.html', '<div class="modal" tabindex="-1" role="dialog" aria-hidden="true"><div class="modal-dialog"><div class="modal-content"><div class="modal-header" ng-show="title"><button type="button" class="close" aria-label="Close" ng-click="$hide()"><span aria-hidden="true">&times;</span></button><h4 class="modal-title" ng-bind="title"></h4></div><div class="modal-body" ng-bind="content"></div><div class="modal-footer"><button type="button" class="btn btn-default" ng-click="$hide()">Close</button></div></div></div></div>')
}]), angular.module('mgcrea.ngStrap.popover').run(['$templateCache', function (t) {
t.put('popover/popover.tpl.html', '<div class="popover"><div class="arrow"></div><h3 class="popover-title" ng-bind="title" ng-show="title"></h3><div class="popover-content" ng-bind="content"></div></div>')
}]), angular.module('mgcrea.ngStrap.select').run(['$templateCache', function (t) {
t.put('select/select.tpl.html', '<ul tabindex="-1" class="select dropdown-menu" ng-show="$isVisible()" role="select"><li ng-if="$showAllNoneButtons"><div class="btn-group" style="margin-bottom: 5px; margin-left: 5px"><button type="button" class="btn btn-default btn-xs" ng-click="$selectAll()">{{$allText}}</button> <button type="button" class="btn btn-default btn-xs" ng-click="$selectNone()">{{$noneText}}</button></div></li><li role="presentation" ng-repeat="match in $matches" ng-class="{active: $isActive($index)}"><a style="cursor: default" role="menuitem" tabindex="-1" ng-click="$select($index, $event)"><i class="{{$iconCheckmark}} pull-right" ng-if="$isMultiple && $isActive($index)"></i> <span ng-bind="match.label"></span></a></li></ul>')
}]), angular.module('mgcrea.ngStrap.timepicker').run(['$templateCache', function (t) {
t.put('timepicker/timepicker.tpl.html', '<div class="dropdown-menu timepicker" style="min-width: 0px;width: auto"><table height="100%"><thead><tr class="text-center"><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$arrowAction(-1, 0)"><i class="{{ $iconUp }}"></i></button></th><th>&nbsp;</th><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$arrowAction(-1, 1)"><i class="{{ $iconUp }}"></i></button></th><th>&nbsp;</th><th><button ng-if="showSeconds" tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$arrowAction(-1, 2)"><i class="{{ $iconUp }}"></i></button></th></tr></thead><tbody><tr ng-repeat="(i, row) in rows"><td class="text-center"><button tabindex="-1" style="width: 100%" type="button" class="btn btn-default" ng-class="{\'btn-primary\': row[0].selected}" ng-click="$select(row[0].date, 0)" ng-disabled="row[0].disabled"><span ng-class="{\'text-muted\': row[0].muted}" ng-bind="row[0].label"></span></button></td><td><span ng-bind="i == midIndex ? timeSeparator : \' \'"></span></td><td class="text-center"><button tabindex="-1" ng-if="row[1].date" style="width: 100%" type="button" class="btn btn-default" ng-class="{\'btn-primary\': row[1].selected}" ng-click="$select(row[1].date, 1)" ng-disabled="row[1].disabled"><span ng-class="{\'text-muted\': row[1].muted}" ng-bind="row[1].label"></span></button></td><td><span ng-bind="i == midIndex ? timeSeparator : \' \'"></span></td><td class="text-center"><button tabindex="-1" ng-if="showSeconds && row[2].date" style="width: 100%" type="button" class="btn btn-default" ng-class="{\'btn-primary\': row[2].selected}" ng-click="$select(row[2].date, 2)" ng-disabled="row[2].disabled"><span ng-class="{\'text-muted\': row[2].muted}" ng-bind="row[2].label"></span></button></td><td ng-if="showAM">&nbsp;</td><td ng-if="showAM"><button tabindex="-1" ng-show="i == midIndex - !isAM * 1" style="width: 100%" type="button" ng-class="{\'btn-primary\': !!isAM}" class="btn btn-default" ng-click="$switchMeridian()" ng-disabled="el.disabled">AM</button> <button tabindex="-1" ng-show="i == midIndex + 1 - !isAM * 1" style="width: 100%" type="button" ng-class="{\'btn-primary\': !isAM}" class="btn btn-default" ng-click="$switchMeridian()" ng-disabled="el.disabled">PM</button></td></tr></tbody><tfoot><tr class="text-center"><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$arrowAction(1, 0)"><i class="{{ $iconDown }}"></i></button></th><th>&nbsp;</th><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$arrowAction(1, 1)"><i class="{{ $iconDown }}"></i></button></th><th>&nbsp;</th><th><button ng-if="showSeconds" tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$arrowAction(1, 2)"><i class="{{ $iconDown }}"></i></button></th></tr></tfoot></table></div>')
}]), angular.module('mgcrea.ngStrap.tab').run(['$templateCache', function (t) {
t.put('tab/tab.tpl.html', '<ul class="nav" ng-class="$navClass" role="tablist"><li role="presentation" ng-repeat="$pane in $panes track by $index" ng-class="[ $index == $panes.$active ? $activeClass : \'\', $pane.disabled ? \'disabled\' : \'\' ]"><a role="tab" data-toggle="tab" ng-click="!$pane.disabled && $setActive($index)" data-index="{{ $index }}" ng-bind-html="$pane.title" aria-controls="$pane.title"></a></li></ul><div ng-transclude class="tab-content"></div>')
}]), angular.module('mgcrea.ngStrap.tooltip').run(['$templateCache', function (t) {
t.put('tooltip/tooltip.tpl.html', '<div class="tooltip in" ng-show="title"><div class="tooltip-arrow"></div><div class="tooltip-inner" ng-bind="title"></div></div>')
}]), angular.module('mgcrea.ngStrap.typeahead').run(['$templateCache', function (t) {
t.put('typeahead/typeahead.tpl.html', '<ul tabindex="-1" class="typeahead dropdown-menu" ng-show="$isVisible()" role="select"><li role="presentation" ng-repeat="match in $matches" ng-class="{active: $index == $activeIndex}"><a role="menuitem" tabindex="-1" ng-click="$select($index, $event)" ng-bind="match.label"></a></li></ul>')
}])
}(window, document);
.toast-title{font-weight:700}.toast-message{word-wrap:break-word}.toast-message a,.toast-message label{color:#fff}.toast-message a:hover{color:#ccc;text-decoration:none}.toast-close-button{position:relative;right:-.3em;top:-.3em;float:right;font-size:20px;font-weight:700;color:#fff;-webkit-text-shadow:0 1px 0 #fff;text-shadow:0 1px 0 #fff;opacity:.8}.toast-close-button:focus,.toast-close-button:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4}button.toast-close-button{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.toast-top-center{top:0;right:0;width:100%}.toast-bottom-center{bottom:0;right:0;width:100%}.toast-top-full-width{top:0;right:0;width:100%}.toast-bottom-full-width{bottom:0;right:0;width:100%}.toast-top-left{top:12px;left:12px}.toast-top-right{top:12px;right:12px}.toast-bottom-right{right:12px;bottom:12px}.toast-bottom-left{bottom:12px;left:12px}#toast-container{position:fixed;z-index:999999}#toast-container *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}#toast-container>div{position:relative;overflow:hidden;margin:0 0 6px;padding:15px 15px 15px 50px;width:300px;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;background-position:15px center;background-repeat:no-repeat;-moz-box-shadow:0 0 12px #999;-webkit-box-shadow:0 0 12px #999;box-shadow:0 0 12px #999;color:#fff;opacity:.8}#toast-container>:hover{-moz-box-shadow:0 0 12px #000;-webkit-box-shadow:0 0 12px #000;box-shadow:0 0 12px #000;opacity:1;cursor:pointer}#toast-container>.toast-info{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=)!important}#toast-container>.toast-error{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=)!important}#toast-container>.toast-success{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==)!important}#toast-container>.toast-warning{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=)!important}#toast-container.toast-bottom-center>div,#toast-container.toast-top-center>div{width:300px;margin:auto}#toast-container.toast-bottom-full-width>div,#toast-container.toast-top-full-width>div{width:96%;margin:auto}.toast{background-color:#030303}.toast-success{background-color:#51a351}.toast-error{background-color:#bd362f}.toast-info{background-color:#2f96b4}.toast-warning{background-color:#f89406}.toast-progress{position:absolute;left:0;bottom:0;height:4px;background-color:#000;opacity:.4}.toast{opacity:1!important}.toast.ng-enter{opacity:0!important;transition:opacity .3s linear}.toast.ng-enter.ng-enter-active{opacity:1!important}.toast.ng-leave{opacity:1;transition:opacity .3s linear}.toast.ng-leave.ng-leave-active{opacity:0!important}@media all and (max-width:240px){#toast-container>div{padding:8px 8px 8px 50px;width:11em}#toast-container .toast-close-button{right:-.2em;top:-.2em}}@media all and (min-width:241px)and (max-width:480px){#toast-container>div{padding:8px 8px 8px 50px;width:18em}#toast-container .toast-close-button{right:-.2em;top:-.2em}}@media all and (min-width:481px)and (max-width:768px){#toast-container>div{padding:15px 15px 15px 50px;width:25em}} .toast-title {
\ No newline at end of file font-weight: 700
}
.toast-message {
word-wrap: break-word
}
.toast-message a, .toast-message label {
color: #fff
}
.toast-message a:hover {
color: #ccc;
text-decoration: none
}
.toast-close-button {
position: relative;
right: -.3em;
top: -.3em;
float: right;
font-size: 20px;
font-weight: 700;
color: #fff;
-webkit-text-shadow: 0 1px 0 #fff;
text-shadow: 0 1px 0 #fff;
opacity: .8
}
.toast-close-button:focus, .toast-close-button:hover {
color: #000;
text-decoration: none;
cursor: pointer;
opacity: .4
}
button.toast-close-button {
padding: 0;
cursor: pointer;
background: 0 0;
border: 0;
-webkit-appearance: none
}
.toast-top-center {
top: 0;
right: 0;
width: 100%
}
.toast-bottom-center {
bottom: 0;
right: 0;
width: 100%
}
.toast-top-full-width {
top: 0;
right: 0;
width: 100%
}
.toast-bottom-full-width {
bottom: 0;
right: 0;
width: 100%
}
.toast-top-left {
top: 12px;
left: 12px
}
.toast-top-right {
top: 12px;
right: 12px
}
.toast-bottom-right {
right: 12px;
bottom: 12px
}
.toast-bottom-left {
bottom: 12px;
left: 12px
}
#toast-container {
position: fixed;
z-index: 999999
}
#toast-container * {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box
}
#toast-container > div {
position: relative;
overflow: hidden;
margin: 0 0 6px;
padding: 15px 15px 15px 50px;
width: 300px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
background-position: 15px center;
background-repeat: no-repeat;
-moz-box-shadow: 0 0 12px #999;
-webkit-box-shadow: 0 0 12px #999;
box-shadow: 0 0 12px #999;
color: #fff;
opacity: .8
}
#toast-container > :hover {
-moz-box-shadow: 0 0 12px #000;
-webkit-box-shadow: 0 0 12px #000;
box-shadow: 0 0 12px #000;
opacity: 1;
cursor: pointer
}
#toast-container > .toast-info {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=) !important
}
#toast-container > .toast-error {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=) !important
}
#toast-container > .toast-success {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==) !important
}
#toast-container > .toast-warning {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=) !important
}
#toast-container.toast-bottom-center > div, #toast-container.toast-top-center > div {
width: 300px;
margin: auto
}
#toast-container.toast-bottom-full-width > div, #toast-container.toast-top-full-width > div {
width: 96%;
margin: auto
}
.toast {
background-color: #030303
}
.toast-success {
background-color: #51a351
}
.toast-error {
background-color: #bd362f
}
.toast-info {
background-color: #2f96b4
}
.toast-warning {
background-color: #f89406
}
.toast-progress {
position: absolute;
left: 0;
bottom: 0;
height: 4px;
background-color: #000;
opacity: .4
}
.toast {
opacity: 1 !important
}
.toast.ng-enter {
opacity: 0 !important;
transition: opacity .3s linear
}
.toast.ng-enter.ng-enter-active {
opacity: 1 !important
}
.toast.ng-leave {
opacity: 1;
transition: opacity .3s linear
}
.toast.ng-leave.ng-leave-active {
opacity: 0 !important
}
@media all and (max-width: 240px) {
#toast-container > div {
padding: 8px 8px 8px 50px;
width: 11em
}
#toast-container .toast-close-button {
right: -.2em;
top: -.2em
}
}
@media all and (min-width: 241px)and (max-width: 480px) {
#toast-container > div {
padding: 8px 8px 8px 50px;
width: 18em
}
#toast-container .toast-close-button {
right: -.2em;
top: -.2em
}
}
@media all and (min-width: 481px)and (max-width: 768px) {
#toast-container > div {
padding: 15px 15px 15px 50px;
width: 25em
}
}
!function(){"use strict";function t(t,e,s,n,o,r,a){function i(t){if(t)d(t.toastId);else for(var e=0;e<O.length;e++)d(O[e].toastId)}function l(t,e,s){var n=m().iconClasses.error;return g(n,t,e,s)}function c(t,e,s){var n=m().iconClasses.info;return g(n,t,e,s)}function u(t,e,s){var n=m().iconClasses.success;return g(n,t,e,s)}function p(t,e,s){var n=m().iconClasses.warning;return g(n,t,e,s)}function d(e,s){function n(t){for(var e=0;e<O.length;e++)if(O[e].toastId===t)return O[e]}function o(){return!O.length}var i=n(e);i&&!i.deleting&&(i.deleting=!0,i.isOpened=!1,t.leave(i.el).then(function(){i.scope.options.onHidden&&i.scope.options.onHidden(s),i.scope.$destroy();var t=O.indexOf(i);delete B[i.scope.message],O.splice(t,1);var e=r.maxOpened;e&&O.length>=e&&O[e-1].open.resolve(),o()&&(h.remove(),h=null,T=a.defer())}))}function g(t,e,s,n){return angular.isObject(s)&&(n=s,s=null),v({iconClass:t,message:e,optionsOverride:n,title:s})}function m(){return angular.extend({},r)}function f(e){if(h)return T.promise;h=angular.element("<div></div>"),h.attr("id",e.containerId),h.addClass(e.positionClass),h.css({"pointer-events":"auto"});var s=angular.element(document.querySelector(e.target));if(!s||!s.length)throw"Target for toasts doesn't exist";return t.enter(h,s).then(function(){T.resolve()}),T.promise}function v(s){function r(t,e,s){s.allowHtml?(t.scope.allowHtml=!0,t.scope.title=o.trustAsHtml(e.title),t.scope.message=o.trustAsHtml(e.message)):(t.scope.title=e.title,t.scope.message=e.message),t.scope.toastType=t.iconClass,t.scope.toastId=t.toastId,t.scope.options={extendedTimeOut:s.extendedTimeOut,messageClass:s.messageClass,onHidden:s.onHidden,onShown:s.onShown,progressBar:s.progressBar,tapToDismiss:s.tapToDismiss,timeOut:s.timeOut,titleClass:s.titleClass,toastClass:s.toastClass},s.closeButton&&(t.scope.options.closeHtml=s.closeHtml)}function i(){function t(t){for(var e=["containerId","iconClasses","maxOpened","newestOnTop","positionClass","preventDuplicates","preventOpenDuplicates","templates"],s=0,n=e.length;n>s;s++)delete t[e[s]];return t}var e={toastId:C++,isOpened:!1,scope:n.$new(),open:a.defer()};return e.iconClass=s.iconClass,s.optionsOverride&&(p=angular.extend(p,t(s.optionsOverride)),e.iconClass=s.optionsOverride.iconClass||e.iconClass),r(e,s,p),e.el=l(e.scope),e}function l(t){var s=angular.element("<div toast></div>"),n=e.get("$compile");return n(s)(t)}function c(){return p.maxOpened&&O.length<=p.maxOpened||!p.maxOpened}function u(){var t=p.preventDuplicates&&s.message===w,e=p.preventOpenDuplicates&&B[s.message];return t||e?!0:(w=s.message,B[s.message]=!0,!1)}var p=m();if(!u()){var g=i();if(O.push(g),p.autoDismiss&&p.maxOpened>0)for(var v=O.slice(0,O.length-p.maxOpened),T=0,$=v.length;$>T;T++)d(v[T].toastId);return c()&&g.open.resolve(),g.open.promise.then(function(){f(p).then(function(){if(g.isOpened=!0,p.newestOnTop)t.enter(g.el,h).then(function(){g.scope.init()});else{var e=h[0].lastChild?angular.element(h[0].lastChild):null;t.enter(g.el,h,e).then(function(){g.scope.init()})}})}),g}}var h,C=0,O=[],w="",B={},T=a.defer(),$={clear:i,error:l,info:c,remove:d,success:u,warning:p};return $}angular.module("toastr",[]).factory("toastr",t),t.$inject=["$animate","$injector","$document","$rootScope","$sce","toastrConfig","$q"]}(),function(){"use strict";angular.module("toastr").constant("toastrConfig",{allowHtml:!1,autoDismiss:!1,closeButton:!1,closeHtml:"<button>&times;</button>",containerId:"toast-container",extendedTimeOut:1e3,iconClasses:{error:"toast-error",info:"toast-info",success:"toast-success",warning:"toast-warning"},maxOpened:0,messageClass:"toast-message",newestOnTop:!0,onHidden:null,onShown:null,positionClass:"toast-top-right",preventDuplicates:!1,preventOpenDuplicates:!1,progressBar:!1,tapToDismiss:!0,target:"body",templates:{toast:"directives/toast/toast.html",progressbar:"directives/progressbar/progressbar.html"},timeOut:5e3,titleClass:"toast-title",toastClass:"toast"})}(),function(){"use strict";function t(t){function e(t,e,s,n){function o(){var t=(i-(new Date).getTime())/a*100;e.css("width",t+"%")}var r,a,i;n.progressBar=t,t.start=function(t){r&&clearInterval(r),a=parseFloat(t),i=(new Date).getTime()+a,r=setInterval(o,10)},t.stop=function(){r&&clearInterval(r)},t.$on("$destroy",function(){clearInterval(r)})}return{replace:!0,require:"^toast",templateUrl:function(){return t.templates.progressbar},link:e}}angular.module("toastr").directive("progressBar",t),t.$inject=["toastrConfig"]}(),function(){"use strict";function t(){this.progressBar=null,this.startProgressBar=function(t){this.progressBar&&this.progressBar.start(t)},this.stopProgressBar=function(){this.progressBar&&this.progressBar.stop()}}angular.module("toastr").controller("ToastController",t)}(),function(){"use strict";function t(t,e,s,n){function o(s,o,r,a){function i(t){return a.startProgressBar(t),e(function(){a.stopProgressBar(),n.remove(s.toastId)},t,1)}function l(){s.progressBar=!1,a.stopProgressBar()}function c(){return s.options.closeHtml}var u;if(s.toastClass=s.options.toastClass,s.titleClass=s.options.titleClass,s.messageClass=s.options.messageClass,s.progressBar=s.options.progressBar,c()){var p=angular.element(s.options.closeHtml),d=t.get("$compile");p.addClass("toast-close-button"),p.attr("ng-click","close()"),d(p)(s),o.prepend(p)}s.init=function(){s.options.timeOut&&(u=i(s.options.timeOut)),s.options.onShown&&s.options.onShown()},o.on("mouseenter",function(){l(),u&&e.cancel(u)}),s.tapToast=function(){s.options.tapToDismiss&&s.close(!0)},s.close=function(t){n.remove(s.toastId,t)},o.on("mouseleave",function(){(0!==s.options.timeOut||0!==s.options.extendedTimeOut)&&(s.$apply(function(){s.progressBar=s.options.progressBar}),u=i(s.options.extendedTimeOut))})}return{replace:!0,templateUrl:function(){return s.templates.toast},controller:"ToastController",link:o}}angular.module("toastr").directive("toast",t),t.$inject=["$injector","$interval","toastrConfig","toastr"]}(),angular.module("toastr").run(["$templateCache",function(t){t.put("directives/progressbar/progressbar.html",'<div class="toast-progress"></div>\n'),t.put("directives/toast/toast.html",'<div class="{{toastClass}} {{toastType}}" ng-click="tapToast()">\n <div ng-switch on="allowHtml">\n <div ng-switch-default ng-if="title" class="{{titleClass}}">{{title}}</div>\n <div ng-switch-default class="{{messageClass}}">{{message}}</div>\n <div ng-switch-when="true" ng-if="title" class="{{titleClass}}" ng-bind-html="title"></div>\n <div ng-switch-when="true" class="{{messageClass}}" ng-bind-html="message"></div>\n </div>\n <progress-bar ng-if="progressBar"></progress-bar>\n</div>\n')}]); !function () {
\ No newline at end of file "use strict";
function t(t, e, s, n, o, r, a) {
function i(t) {
if (t)d(t.toastId); else for (var e = 0; e < O.length; e++)d(O[e].toastId)
}
function l(t, e, s) {
var n = m().iconClasses.error;
return g(n, t, e, s)
}
function c(t, e, s) {
var n = m().iconClasses.info;
return g(n, t, e, s)
}
function u(t, e, s) {
var n = m().iconClasses.success;
return g(n, t, e, s)
}
function p(t, e, s) {
var n = m().iconClasses.warning;
return g(n, t, e, s)
}
function d(e, s) {
function n(t) {
for (var e = 0; e < O.length; e++)if (O[e].toastId === t)return O[e]
}
function o() {
return !O.length
}
var i = n(e);
i && !i.deleting && (i.deleting = !0, i.isOpened = !1, t.leave(i.el).then(function () {
i.scope.options.onHidden && i.scope.options.onHidden(s), i.scope.$destroy();
var t = O.indexOf(i);
delete B[i.scope.message], O.splice(t, 1);
var e = r.maxOpened;
e && O.length >= e && O[e - 1].open.resolve(), o() && (h.remove(), h = null, T = a.defer())
}))
}
function g(t, e, s, n) {
return angular.isObject(s) && (n = s, s = null), v({iconClass: t, message: e, optionsOverride: n, title: s})
}
function m() {
return angular.extend({}, r)
}
function f(e) {
if (h)return T.promise;
h = angular.element("<div></div>"), h.attr("id", e.containerId), h.addClass(e.positionClass), h.css({"pointer-events": "auto"});
var s = angular.element(document.querySelector(e.target));
if (!s || !s.length)throw"Target for toasts doesn't exist";
return t.enter(h, s).then(function () {
T.resolve()
}), T.promise
}
function v(s) {
function r(t, e, s) {
s.allowHtml ? (t.scope.allowHtml = !0, t.scope.title = o.trustAsHtml(e.title), t.scope.message = o.trustAsHtml(e.message)) : (t.scope.title = e.title, t.scope.message = e.message), t.scope.toastType = t.iconClass, t.scope.toastId = t.toastId, t.scope.options = {
extendedTimeOut: s.extendedTimeOut,
messageClass: s.messageClass,
onHidden: s.onHidden,
onShown: s.onShown,
progressBar: s.progressBar,
tapToDismiss: s.tapToDismiss,
timeOut: s.timeOut,
titleClass: s.titleClass,
toastClass: s.toastClass
}, s.closeButton && (t.scope.options.closeHtml = s.closeHtml)
}
function i() {
function t(t) {
for (var e = ["containerId", "iconClasses", "maxOpened", "newestOnTop", "positionClass", "preventDuplicates", "preventOpenDuplicates", "templates"], s = 0, n = e.length; n > s; s++)delete t[e[s]];
return t
}
var e = {toastId: C++, isOpened: !1, scope: n.$new(), open: a.defer()};
return e.iconClass = s.iconClass, s.optionsOverride && (p = angular.extend(p, t(s.optionsOverride)), e.iconClass = s.optionsOverride.iconClass || e.iconClass), r(e, s, p), e.el = l(e.scope), e
}
function l(t) {
var s = angular.element("<div toast></div>"), n = e.get("$compile");
return n(s)(t)
}
function c() {
return p.maxOpened && O.length <= p.maxOpened || !p.maxOpened
}
function u() {
var t = p.preventDuplicates && s.message === w, e = p.preventOpenDuplicates && B[s.message];
return t || e ? !0 : (w = s.message, B[s.message] = !0, !1)
}
var p = m();
if (!u()) {
var g = i();
if (O.push(g), p.autoDismiss && p.maxOpened > 0)for (var v = O.slice(0, O.length - p.maxOpened), T = 0, $ = v.length; $ > T; T++)d(v[T].toastId);
return c() && g.open.resolve(), g.open.promise.then(function () {
f(p).then(function () {
if (g.isOpened = !0, p.newestOnTop)t.enter(g.el, h).then(function () {
g.scope.init()
}); else {
var e = h[0].lastChild ? angular.element(h[0].lastChild) : null;
t.enter(g.el, h, e).then(function () {
g.scope.init()
})
}
})
}), g
}
}
var h, C = 0, O = [], w = "", B = {}, T = a.defer(), $ = {
clear: i,
error: l,
info: c,
remove: d,
success: u,
warning: p
};
return $
}
angular.module("toastr", []).factory("toastr", t), t.$inject = ["$animate", "$injector", "$document", "$rootScope", "$sce", "toastrConfig", "$q"]
}(), function () {
"use strict";
angular.module("toastr").constant("toastrConfig", {
allowHtml: !1,
autoDismiss: !1,
closeButton: !1,
closeHtml: "<button>&times;</button>",
containerId: "toast-container",
extendedTimeOut: 1e3,
iconClasses: {error: "toast-error", info: "toast-info", success: "toast-success", warning: "toast-warning"},
maxOpened: 0,
messageClass: "toast-message",
newestOnTop: !0,
onHidden: null,
onShown: null,
positionClass: "toast-top-right",
preventDuplicates: !1,
preventOpenDuplicates: !1,
progressBar: !1,
tapToDismiss: !0,
target: "body",
templates: {toast: "directives/toast/toast.html", progressbar: "directives/progressbar/progressbar.html"},
timeOut: 5e3,
titleClass: "toast-title",
toastClass: "toast"
})
}(), function () {
"use strict";
function t(t) {
function e(t, e, s, n) {
function o() {
var t = (i - (new Date).getTime()) / a * 100;
e.css("width", t + "%")
}
var r, a, i;
n.progressBar = t, t.start = function (t) {
r && clearInterval(r), a = parseFloat(t), i = (new Date).getTime() + a, r = setInterval(o, 10)
}, t.stop = function () {
r && clearInterval(r)
}, t.$on("$destroy", function () {
clearInterval(r)
})
}
return {
replace: !0, require: "^toast", templateUrl: function () {
return t.templates.progressbar
}, link: e
}
}
angular.module("toastr").directive("progressBar", t), t.$inject = ["toastrConfig"]
}(), function () {
"use strict";
function t() {
this.progressBar = null, this.startProgressBar = function (t) {
this.progressBar && this.progressBar.start(t)
}, this.stopProgressBar = function () {
this.progressBar && this.progressBar.stop()
}
}
angular.module("toastr").controller("ToastController", t)
}(), function () {
"use strict";
function t(t, e, s, n) {
function o(s, o, r, a) {
function i(t) {
return a.startProgressBar(t), e(function () {
a.stopProgressBar(), n.remove(s.toastId)
}, t, 1)
}
function l() {
s.progressBar = !1, a.stopProgressBar()
}
function c() {
return s.options.closeHtml
}
var u;
if (s.toastClass = s.options.toastClass, s.titleClass = s.options.titleClass, s.messageClass = s.options.messageClass, s.progressBar = s.options.progressBar, c()) {
var p = angular.element(s.options.closeHtml), d = t.get("$compile");
p.addClass("toast-close-button"), p.attr("ng-click", "close()"), d(p)(s), o.prepend(p)
}
s.init = function () {
s.options.timeOut && (u = i(s.options.timeOut)), s.options.onShown && s.options.onShown()
}, o.on("mouseenter", function () {
l(), u && e.cancel(u)
}), s.tapToast = function () {
s.options.tapToDismiss && s.close(!0)
}, s.close = function (t) {
n.remove(s.toastId, t)
}, o.on("mouseleave", function () {
(0 !== s.options.timeOut || 0 !== s.options.extendedTimeOut) && (s.$apply(function () {
s.progressBar = s.options.progressBar
}), u = i(s.options.extendedTimeOut))
})
}
return {
replace: !0, templateUrl: function () {
return s.templates.toast
}, controller: "ToastController", link: o
}
}
angular.module("toastr").directive("toast", t), t.$inject = ["$injector", "$interval", "toastrConfig", "toastr"]
}(), angular.module("toastr").run(["$templateCache", function (t) {
t.put("directives/progressbar/progressbar.html", '<div class="toast-progress"></div>\n'), t.put("directives/toast/toast.html", '<div class="{{toastClass}} {{toastType}}" ng-click="tapToast()">\n <div ng-switch on="allowHtml">\n <div ng-switch-default ng-if="title" class="{{titleClass}}">{{title}}</div>\n <div ng-switch-default class="{{messageClass}}">{{message}}</div>\n <div ng-switch-when="true" ng-if="title" class="{{titleClass}}" ng-bind-html="title"></div>\n <div ng-switch-when="true" class="{{messageClass}}" ng-bind-html="message"></div>\n </div>\n <progress-bar ng-if="progressBar"></progress-bar>\n</div>\n')
}]);
This source diff could not be displayed because it is too large. You can view the blob instead.
"use strict";angular.module("lr.upload",["lr.upload.formdata","lr.upload.iframe","lr.upload.directives"]),angular.module("lr.upload.directives",[]),angular.module("lr.upload.directives").directive("uploadButton",["upload",function(a){return{restrict:"EA",scope:{data:"=?data",url:"@",id:"@",param:"@",method:"@",onUpload:"&",onSuccess:"&",onError:"&",onComplete:"&"},link:function(b,c,d){var e=angular.element(c),f=angular.element('<input id="'+b.id+'" type="file" />');if(e.append(f),f.on("change",function(){var c=angular.element(this);if(!c[0].files||0!==c[0].files.length){var e={url:b.url,method:b.method||"POST",forceIFrameUpload:b.$eval(d.forceIframeUpload)||!1,data:b.data||{}};e.data[b.param||"file"]=c,b.$apply(function(){b.onUpload({files:c[0].files})}),a(e).then(function(a){b.onSuccess({response:a}),b.onComplete({response:a})},function(a){b.onError({response:a}),b.onComplete({response:a})})}}),"required"in d&&d.$observe("required",function(a){var d=""===a?!0:b.$eval(a);f.attr("required",d),c.toggleClass("ng-valid",!d),c.toggleClass("ng-invalid ng-invalid-required",d)}),"accept"in d&&d.$observe("accept",function(a){f.attr("accept",a)}),a.support.formData){var g=function(){f.attr("multiple",!(!b.$eval(d.multiple)||b.$eval(d.forceIframeUpload)))};d.$observe("multiple",g),d.$observe("forceIframeUpload",g)}}}}]),angular.module("lr.upload.formdata",[]).factory("formDataTransform",function(){return function(a){var b=new FormData;return angular.forEach(a,function(a,c){if(angular.isElement(a)){var d=[];angular.forEach(a,function(a){angular.forEach(a.files,function(a){d.push(a)}),a.value=""}),0!==d.length&&(d.length>1?angular.forEach(d,function(a,d){b.append(c+"["+d+"]",a)}):b.append(c,d[0]))}else b.append(c,a)}),b}}).factory("formDataUpload",["$http","formDataTransform",function(a,b){return function(c){return c.transformRequest=b,c.method=c.method||"POST",c.headers=angular.extend(c.headers||{},{"Content-Type":void 0}),a(c)}}]),angular.module("lr.upload.iframe",[]).factory("iFrameUpload",["$q","$http","$document","$rootScope",function(a,b,c,d){function e(a,b){if(a.indexOf)return a.indexOf(b);for(var c=0;c<a.length;c++)if(b===a[c])return c;return-1}function f(f){var g=[],h=a.defer(),i=h.promise;angular.forEach(f.data||{},function(a,b){angular.isElement(a)&&(delete f.data[b],a.attr("name",b),g.push(a))});var j=/\?/.test(f.url)?"&":"?";"DELETE"===f.method?(f.url=f.url+j+"_method=DELETE",f.method="POST"):"PUT"===f.method?(f.url=f.url+j+"_method=PUT",f.method="POST"):"PATCH"===f.method&&(f.url=f.url+j+"_method=PATCH",f.method="POST");var k=angular.element(c[0].body),l=d.$new(),m="iframe-transport-"+l.$id;l.$destroy();var n=angular.element("<form></form>");n.attr("target",m),n.attr("action",f.url),n.attr("method",f.method||"POST"),n.css("display","none"),g.length&&(n.attr("enctype","multipart/form-data"),n.attr("encoding","multipart/form-data"));var o=angular.element('<iframe name="'+m+'" src="javascript:false;"></iframe>');return o.on("load",function(){function a(a,b){var c=[];return angular.isFunction(b)?b(a,c):(angular.forEach(b,function(b){a=b(a,c)}),a)}function c(){var a=e(b.pendingRequests,f);-1!==a&&(b.pendingRequests.splice(a,1),f.$iframeTransportForm.remove(),delete f.$iframeTransportForm)}o.off("load").on("load",function(){var c;try{var d=this.contentWindow?this.contentWindow.document:this.contentDocument;if(c=angular.element(d.body).text(),!c.length)throw new Error}catch(e){}n.append(angular.element('<iframe src="javascript:false;"></iframe>'));try{c=a(c,b.defaults.transformResponse)}catch(e){}h.resolve({data:c,status:200,headers:[],config:f})}),angular.forEach(f.data,function(a,b){var c=angular.element('<input type="hidden" />');c.attr("name",b),c.val(a),n.append(c)}),angular.forEach(g,function(a){var b=a.clone(!0);a.after(b),n.append(a)}),f.$iframeTransportForm=n,b.pendingRequests.push(f),n[0].submit(),i.then(c,c)}),n.append(o),k.append(n),i}return f}]),angular.module("lr.upload").factory("upload",["$window","formDataUpload","iFrameUpload",function(a,b,c){function d(a){return e.formData&&!a.forceIFrameUpload?b(a):c(a)}var e={fileInput:!(new RegExp("(Android (1\\.[0156]|2\\.[01]))|(Windows Phone (OS 7|8\\.0))|(XBLWP)|(ZuneWP)|(WPDesktop)|(w(eb)?OSBrowser)|(webOS)|(Kindle/(1\\.0|2\\.[05]|3\\.0))").test(a.navigator.userAgent)||angular.element('<input type="file">').prop("disabled")),fileUpload:!(!a.XMLHttpRequestUpload||!a.FileReader),formData:!!a.FormData};return d.support=e,d}]); "use strict";
\ No newline at end of file angular.module("lr.upload", ["lr.upload.formdata", "lr.upload.iframe", "lr.upload.directives"]), angular.module("lr.upload.directives", []), angular.module("lr.upload.directives").directive("uploadButton", ["upload", function (a) {
return {
restrict: "EA",
scope: {
data: "=?data",
url: "@",
id: "@",
param: "@",
method: "@",
onUpload: "&",
onSuccess: "&",
onError: "&",
onComplete: "&"
},
link: function (b, c, d) {
var e = angular.element(c), f = angular.element('<input id="' + b.id + '" type="file" />');
if (e.append(f), f.on("change", function () {
var c = angular.element(this);
if (!c[0].files || 0 !== c[0].files.length) {
var e = {
url: b.url,
method: b.method || "POST",
forceIFrameUpload: b.$eval(d.forceIframeUpload) || !1,
data: b.data || {}
};
e.data[b.param || "file"] = c, b.$apply(function () {
b.onUpload({files: c[0].files})
}), a(e).then(function (a) {
b.onSuccess({response: a}), b.onComplete({response: a})
}, function (a) {
b.onError({response: a}), b.onComplete({response: a})
})
}
}), "required" in d && d.$observe("required", function (a) {
var d = "" === a ? !0 : b.$eval(a);
f.attr("required", d), c.toggleClass("ng-valid", !d), c.toggleClass("ng-invalid ng-invalid-required", d)
}), "accept" in d && d.$observe("accept", function (a) {
f.attr("accept", a)
}), a.support.formData) {
var g = function () {
f.attr("multiple", !(!b.$eval(d.multiple) || b.$eval(d.forceIframeUpload)))
};
d.$observe("multiple", g), d.$observe("forceIframeUpload", g)
}
}
}
}]), angular.module("lr.upload.formdata", []).factory("formDataTransform", function () {
return function (a) {
var b = new FormData;
return angular.forEach(a, function (a, c) {
if (angular.isElement(a)) {
var d = [];
angular.forEach(a, function (a) {
angular.forEach(a.files, function (a) {
d.push(a)
}), a.value = ""
}), 0 !== d.length && (d.length > 1 ? angular.forEach(d, function (a, d) {
b.append(c + "[" + d + "]", a)
}) : b.append(c, d[0]))
} else b.append(c, a)
}), b
}
}).factory("formDataUpload", ["$http", "formDataTransform", function (a, b) {
return function (c) {
return c.transformRequest = b, c.method = c.method || "POST", c.headers = angular.extend(c.headers || {}, {"Content-Type": void 0}), a(c)
}
}]), angular.module("lr.upload.iframe", []).factory("iFrameUpload", ["$q", "$http", "$document", "$rootScope", function (a, b, c, d) {
function e(a, b) {
if (a.indexOf)return a.indexOf(b);
for (var c = 0; c < a.length; c++)if (b === a[c])return c;
return -1
}
function f(f) {
var g = [], h = a.defer(), i = h.promise;
angular.forEach(f.data || {}, function (a, b) {
angular.isElement(a) && (delete f.data[b], a.attr("name", b), g.push(a))
});
var j = /\?/.test(f.url) ? "&" : "?";
"DELETE" === f.method ? (f.url = f.url + j + "_method=DELETE", f.method = "POST") : "PUT" === f.method ? (f.url = f.url + j + "_method=PUT", f.method = "POST") : "PATCH" === f.method && (f.url = f.url + j + "_method=PATCH", f.method = "POST");
var k = angular.element(c[0].body), l = d.$new(), m = "iframe-transport-" + l.$id;
l.$destroy();
var n = angular.element("<form></form>");
n.attr("target", m), n.attr("action", f.url), n.attr("method", f.method || "POST"), n.css("display", "none"), g.length && (n.attr("enctype", "multipart/form-data"), n.attr("encoding", "multipart/form-data"));
var o = angular.element('<iframe name="' + m + '" src="javascript:false;"></iframe>');
return o.on("load", function () {
function a(a, b) {
var c = [];
return angular.isFunction(b) ? b(a, c) : (angular.forEach(b, function (b) {
a = b(a, c)
}), a)
}
function c() {
var a = e(b.pendingRequests, f);
-1 !== a && (b.pendingRequests.splice(a, 1), f.$iframeTransportForm.remove(), delete f.$iframeTransportForm)
}
o.off("load").on("load", function () {
var c;
try {
var d = this.contentWindow ? this.contentWindow.document : this.contentDocument;
if (c = angular.element(d.body).text(), !c.length)throw new Error
} catch (e) {
}
n.append(angular.element('<iframe src="javascript:false;"></iframe>'));
try {
c = a(c, b.defaults.transformResponse)
} catch (e) {
}
h.resolve({data: c, status: 200, headers: [], config: f})
}), angular.forEach(f.data, function (a, b) {
var c = angular.element('<input type="hidden" />');
c.attr("name", b), c.val(a), n.append(c)
}), angular.forEach(g, function (a) {
var b = a.clone(!0);
a.after(b), n.append(a)
}), f.$iframeTransportForm = n, b.pendingRequests.push(f), n[0].submit(), i.then(c, c)
}), n.append(o), k.append(n), i
}
return f
}]), angular.module("lr.upload").factory("upload", ["$window", "formDataUpload", "iFrameUpload", function (a, b, c) {
function d(a) {
return e.formData && !a.forceIFrameUpload ? b(a) : c(a)
}
var e = {
fileInput: !(new RegExp("(Android (1\\.[0156]|2\\.[01]))|(Windows Phone (OS 7|8\\.0))|(XBLWP)|(ZuneWP)|(WPDesktop)|(w(eb)?OSBrowser)|(webOS)|(Kindle/(1\\.0|2\\.[05]|3\\.0))").test(a.navigator.userAgent) || angular.element('<input type="file">').prop("disabled")),
fileUpload: !(!a.XMLHttpRequestUpload || !a.FileReader),
formData: !!a.FormData
};
return d.support = e, d
}]);
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -3,4 +3,265 @@ ...@@ -3,4 +3,265 @@
* *
* http://bootboxjs.com/license.txt * http://bootboxjs.com/license.txt
*/ */
!function(a,b){"use strict";"function"==typeof define&&define.amd?define(["jquery"],b):"object"==typeof exports?module.exports=b(require("jquery")):a.bootbox=b(a.jQuery)}(this,function a(b,c){"use strict";function d(a){var b=q[o.locale];return b?b[a]:q.en[a]}function e(a,c,d){a.stopPropagation(),a.preventDefault();var e=b.isFunction(d)&&d.call(c,a)===!1;e||c.modal("hide")}function f(a){var b,c=0;for(b in a)c++;return c}function g(a,c){var d=0;b.each(a,function(a,b){c(a,b,d++)})}function h(a){var c,d;if("object"!=typeof a)throw new Error("Please supply an object of options");if(!a.message)throw new Error("Please specify a message");return a=b.extend({},o,a),a.buttons||(a.buttons={}),c=a.buttons,d=f(c),g(c,function(a,e,f){if(b.isFunction(e)&&(e=c[a]={callback:e}),"object"!==b.type(e))throw new Error("button with key "+a+" must be an object");e.label||(e.label=a),e.className||(e.className=2>=d&&f===d-1?"btn-success":"btn-danger")}),a}function i(a,b){var c=a.length,d={};if(1>c||c>2)throw new Error("Invalid argument length");return 2===c||"string"==typeof a[0]?(d[b[0]]=a[0],d[b[1]]=a[1]):d=a[0],d}function j(a,c,d){return b.extend(!0,{},a,i(c,d))}function k(a,b,c,d){var e={className:"bootbox-"+a,buttons:l.apply(null,b)};return m(j(e,d,c),b)}function l(){for(var a={},b=0,c=arguments.length;c>b;b++){var e=arguments[b],f=e.toLowerCase(),g=e.toUpperCase();a[f]={label:d(g)}}return a}function m(a,b){var d={};return g(b,function(a,b){d[b]=!0}),g(a.buttons,function(a){if(d[a]===c)throw new Error("button key "+a+" is not allowed (options are "+b.join("\n")+")")}),a}var n={dialog:"<div class='bootbox modal' tabindex='-1' role='dialog'><div class='modal-dialog'><div class='modal-content'><div class='modal-body'><div class='bootbox-body'></div></div></div></div></div>",header:"<div class='modal-header'><h4 class='modal-title'></h4></div>",footer:"<div class='modal-footer'></div>",closeButton:"<button type='button' class='bootbox-close-button close' data-dismiss='modal' aria-hidden='true'>&times;</button>",form:"<form class='bootbox-form'></form>",inputs:{text:"<input class='bootbox-input bootbox-input-text form-control' autocomplete=off type=text />",textarea:"<textarea class='bootbox-input bootbox-input-textarea form-control'></textarea>",email:"<input class='bootbox-input bootbox-input-email form-control' autocomplete='off' type='email' />",select:"<select class='bootbox-input bootbox-input-select form-control'></select>",checkbox:"<div class='checkbox'><label><input class='bootbox-input bootbox-input-checkbox' type='checkbox' /></label></div>",date:"<input class='bootbox-input bootbox-input-date form-control' autocomplete=off type='date' />",time:"<input class='bootbox-input bootbox-input-time form-control' autocomplete=off type='time' />",number:"<input class='bootbox-input bootbox-input-number form-control' autocomplete=off type='number' />",password:"<input class='bootbox-input bootbox-input-password form-control' autocomplete='off' type='password' />"}},o={locale:"zh_CN",backdrop:"static",animate:!0,className:null,closeButton:!0,show:!0,container:"body"},p={};p.alert=function(){var a;if(a=k("alert",["ok"],["message","callback"],arguments),a.callback&&!b.isFunction(a.callback))throw new Error("alert requires callback property to be a function when provided");return a.buttons.ok.callback=a.onEscape=function(){return b.isFunction(a.callback)?a.callback.call(this):!0},p.dialog(a)},p.confirm=function(){var a;if(a=k("confirm",["cancel","confirm"],["message","callback"],arguments),a.buttons.cancel.callback=a.onEscape=function(){return a.callback.call(this,!1)},a.buttons.confirm.callback=function(){return a.callback.call(this,!0)},!b.isFunction(a.callback))throw new Error("confirm requires a callback");return p.dialog(a)},p.prompt=function(){var a,d,e,f,h,i,k;if(f=b(n.form),d={className:"bootbox-prompt",buttons:l("cancel","confirm"),value:"",inputType:"text"},a=m(j(d,arguments,["title","callback"]),["cancel","confirm"]),i=a.show===c?!0:a.show,a.message=f,a.buttons.cancel.callback=a.onEscape=function(){return a.callback.call(this,null)},a.buttons.confirm.callback=function(){var c;switch(a.inputType){case"text":case"textarea":case"email":case"select":case"date":case"time":case"number":case"password":c=h.val();break;case"checkbox":var d=h.find("input:checked");c=[],g(d,function(a,d){c.push(b(d).val())})}return a.callback.call(this,c)},a.show=!1,!a.title)throw new Error("prompt requires a title");if(!b.isFunction(a.callback))throw new Error("prompt requires a callback");if(!n.inputs[a.inputType])throw new Error("invalid prompt type");switch(h=b(n.inputs[a.inputType]),a.inputType){case"text":case"textarea":case"email":case"date":case"time":case"number":case"password":h.val(a.value);break;case"select":var o={};if(k=a.inputOptions||[],!b.isArray(k))throw new Error("Please pass an array of input options");if(!k.length)throw new Error("prompt with select requires options");g(k,function(a,d){var e=h;if(d.value===c||d.text===c)throw new Error("given options in wrong format");d.group&&(o[d.group]||(o[d.group]=b("<optgroup/>").attr("label",d.group)),e=o[d.group]),e.append("<option value='"+d.value+"'>"+d.text+"</option>")}),g(o,function(a,b){h.append(b)}),h.val(a.value);break;case"checkbox":var q=b.isArray(a.value)?a.value:[a.value];if(k=a.inputOptions||[],!k.length)throw new Error("prompt with checkbox requires options");if(!k[0].value||!k[0].text)throw new Error("given options in wrong format");h=b("<div/>"),g(k,function(c,d){var e=b(n.inputs[a.inputType]);e.find("input").attr("value",d.value),e.find("label").append(d.text),g(q,function(a,b){b===d.value&&e.find("input").prop("checked",!0)}),h.append(e)})}return a.placeholder&&h.attr("placeholder",a.placeholder),a.pattern&&h.attr("pattern",a.pattern),a.maxlength&&h.attr("maxlength",a.maxlength),f.append(h),f.on("submit",function(a){a.preventDefault(),a.stopPropagation(),e.find(".btn-primary").click()}),e=p.dialog(a),e.off("shown.bs.modal"),e.on("shown.bs.modal",function(){h.focus()}),i===!0&&e.modal("show"),e},p.dialog=function(a){a=h(a);var d=b(n.dialog),f=d.find(".modal-dialog"),i=d.find(".modal-body"),j=a.buttons,k="",l={onEscape:a.onEscape};if(b.fn.modal===c)throw new Error("$.fn.modal is not defined; please double check you have included the Bootstrap JavaScript library. See http://getbootstrap.com/javascript/ for more details.");if(g(j,function(a,b){k+="<button data-bb-handler='"+a+"' type='button' class='btn "+b.className+"'>"+b.label+"</button>&emsp;",l[a]=b.callback}),i.find(".bootbox-body").html(a.message),a.animate===!0&&d.addClass("fade"),a.className&&d.addClass(a.className),"large"===a.size?f.addClass("modal-lg"):"small"===a.size&&f.addClass("modal-sm"),a.title&&i.before(n.header),a.closeButton){var m=b(n.closeButton);a.title?d.find(".modal-header").prepend(m):m.css("margin-top","-10px").prependTo(i)}return a.title&&d.find(".modal-title").html(a.title),k.length&&(i.after(n.footer),d.find(".modal-footer").html(k)),d.on("hidden.bs.modal",function(a){a.target===this&&d.remove()}),d.on("shown.bs.modal",function(){d.find(".btn-primary:first").focus()}),"static"!==a.backdrop&&d.on("click.dismiss.bs.modal",function(a){d.children(".modal-backdrop").length&&(a.currentTarget=d.children(".modal-backdrop").get(0)),a.target===a.currentTarget&&d.trigger("escape.close.bb")}),d.on("escape.close.bb",function(a){l.onEscape&&e(a,d,l.onEscape)}),d.on("click",".modal-footer button",function(a){var c=b(this).data("bb-handler");e(a,d,l[c])}),d.on("click",".bootbox-close-button",function(a){e(a,d,l.onEscape)}),d.on("keyup",function(a){27===a.which&&d.trigger("escape.close.bb")}),b(a.container).append(d),d.modal({backdrop:a.backdrop?"static":!1,keyboard:!1,show:!1}),a.show&&d.modal("show"),d},p.setDefaults=function(){var a={};2===arguments.length?a[arguments[0]]=arguments[1]:a=arguments[0],b.extend(o,a)},p.hideAll=function(){return b(".bootbox").modal("hide"),p};var q={bg_BG:{OK:"Ок",CANCEL:"Отказ",CONFIRM:"Потвърждавам"},br:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Sim"},cs:{OK:"OK",CANCEL:"Zrušit",CONFIRM:"Potvrdit"},da:{OK:"OK",CANCEL:"Annuller",CONFIRM:"Accepter"},de:{OK:"OK",CANCEL:"Abbrechen",CONFIRM:"Akzeptieren"},el:{OK:"Εντάξει",CANCEL:"Ακύρωση",CONFIRM:"Επιβεβαίωση"},en:{OK:"OK",CANCEL:"Cancel",CONFIRM:"OK"},es:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Aceptar"},et:{OK:"OK",CANCEL:"Katkesta",CONFIRM:"OK"},fa:{OK:"قبول",CANCEL:"لغو",CONFIRM:"تایید"},fi:{OK:"OK",CANCEL:"Peruuta",CONFIRM:"OK"},fr:{OK:"OK",CANCEL:"Annuler",CONFIRM:"D'accord"},he:{OK:"אישור",CANCEL:"ביטול",CONFIRM:"אישור"},hu:{OK:"OK",CANCEL:"Mégsem",CONFIRM:"Megerősít"},hr:{OK:"OK",CANCEL:"Odustani",CONFIRM:"Potvrdi"},id:{OK:"OK",CANCEL:"Batal",CONFIRM:"OK"},it:{OK:"OK",CANCEL:"Annulla",CONFIRM:"Conferma"},ja:{OK:"OK",CANCEL:"キャンセル",CONFIRM:"確認"},lt:{OK:"Gerai",CANCEL:"Atšaukti",CONFIRM:"Patvirtinti"},lv:{OK:"Labi",CANCEL:"Atcelt",CONFIRM:"Apstiprināt"},nl:{OK:"OK",CANCEL:"Annuleren",CONFIRM:"Accepteren"},no:{OK:"OK",CANCEL:"Avbryt",CONFIRM:"OK"},pl:{OK:"OK",CANCEL:"Anuluj",CONFIRM:"Potwierdź"},pt:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Confirmar"},ru:{OK:"OK",CANCEL:"Отмена",CONFIRM:"Применить"},sq:{OK:"OK",CANCEL:"Anulo",CONFIRM:"Prano"},sv:{OK:"OK",CANCEL:"Avbryt",CONFIRM:"OK"},th:{OK:"ตกลง",CANCEL:"ยกเลิก",CONFIRM:"ยืนยัน"},tr:{OK:"Tamam",CANCEL:"İptal",CONFIRM:"Onayla"},zh_CN:{OK:"确定",CANCEL:"取消",CONFIRM:"确认"},zh_TW:{OK:"OK",CANCEL:"取消",CONFIRM:"確認"}};return p.addLocale=function(a,c){return b.each(["OK","CANCEL","CONFIRM"],function(a,b){if(!c[b])throw new Error("Please supply a translation for '"+b+"'")}),q[a]={OK:c.OK,CANCEL:c.CANCEL,CONFIRM:c.CONFIRM},p},p.removeLocale=function(a){return delete q[a],p},p.setLocale=function(a){return p.setDefaults("locale",a)},p.init=function(c){return a(c||b)},p}); !function (a, b) {
\ No newline at end of file "use strict";
"function" == typeof define && define.amd ? define(["jquery"], b) : "object" == typeof exports ? module.exports = b(require("jquery")) : a.bootbox = b(a.jQuery)
}(this, function a(b, c) {
"use strict";
function d(a) {
var b = q[o.locale];
return b ? b[a] : q.en[a]
}
function e(a, c, d) {
a.stopPropagation(), a.preventDefault();
var e = b.isFunction(d) && d.call(c, a) === !1;
e || c.modal("hide")
}
function f(a) {
var b, c = 0;
for (b in a)c++;
return c
}
function g(a, c) {
var d = 0;
b.each(a, function (a, b) {
c(a, b, d++)
})
}
function h(a) {
var c, d;
if ("object" != typeof a)throw new Error("Please supply an object of options");
if (!a.message)throw new Error("Please specify a message");
return a = b.extend({}, o, a), a.buttons || (a.buttons = {}), c = a.buttons, d = f(c), g(c, function (a, e, f) {
if (b.isFunction(e) && (e = c[a] = {callback: e}), "object" !== b.type(e))throw new Error("button with key " + a + " must be an object");
e.label || (e.label = a), e.className || (e.className = 2 >= d && f === d - 1 ? "btn-success" : "btn-danger")
}), a
}
function i(a, b) {
var c = a.length, d = {};
if (1 > c || c > 2)throw new Error("Invalid argument length");
return 2 === c || "string" == typeof a[0] ? (d[b[0]] = a[0], d[b[1]] = a[1]) : d = a[0], d
}
function j(a, c, d) {
return b.extend(!0, {}, a, i(c, d))
}
function k(a, b, c, d) {
var e = {className: "bootbox-" + a, buttons: l.apply(null, b)};
return m(j(e, d, c), b)
}
function l() {
for (var a = {}, b = 0, c = arguments.length; c > b; b++) {
var e = arguments[b], f = e.toLowerCase(), g = e.toUpperCase();
a[f] = {label: d(g)}
}
return a
}
function m(a, b) {
var d = {};
return g(b, function (a, b) {
d[b] = !0
}), g(a.buttons, function (a) {
if (d[a] === c)throw new Error("button key " + a + " is not allowed (options are " + b.join("\n") + ")")
}), a
}
var n = {
dialog: "<div class='bootbox modal' tabindex='-1' role='dialog'><div class='modal-dialog'><div class='modal-content'><div class='modal-body'><div class='bootbox-body'></div></div></div></div></div>",
header: "<div class='modal-header'><h4 class='modal-title'></h4></div>",
footer: "<div class='modal-footer'></div>",
closeButton: "<button type='button' class='bootbox-close-button close' data-dismiss='modal' aria-hidden='true'>&times;</button>",
form: "<form class='bootbox-form'></form>",
inputs: {
text: "<input class='bootbox-input bootbox-input-text form-control' autocomplete=off type=text />",
textarea: "<textarea class='bootbox-input bootbox-input-textarea form-control'></textarea>",
email: "<input class='bootbox-input bootbox-input-email form-control' autocomplete='off' type='email' />",
select: "<select class='bootbox-input bootbox-input-select form-control'></select>",
checkbox: "<div class='checkbox'><label><input class='bootbox-input bootbox-input-checkbox' type='checkbox' /></label></div>",
date: "<input class='bootbox-input bootbox-input-date form-control' autocomplete=off type='date' />",
time: "<input class='bootbox-input bootbox-input-time form-control' autocomplete=off type='time' />",
number: "<input class='bootbox-input bootbox-input-number form-control' autocomplete=off type='number' />",
password: "<input class='bootbox-input bootbox-input-password form-control' autocomplete='off' type='password' />"
}
}, o = {
locale: "zh_CN",
backdrop: "static",
animate: !0,
className: null,
closeButton: !0,
show: !0,
container: "body"
}, p = {};
p.alert = function () {
var a;
if (a = k("alert", ["ok"], ["message", "callback"], arguments), a.callback && !b.isFunction(a.callback))throw new Error("alert requires callback property to be a function when provided");
return a.buttons.ok.callback = a.onEscape = function () {
return b.isFunction(a.callback) ? a.callback.call(this) : !0
}, p.dialog(a)
}, p.confirm = function () {
var a;
if (a = k("confirm", ["cancel", "confirm"], ["message", "callback"], arguments), a.buttons.cancel.callback = a.onEscape = function () {
return a.callback.call(this, !1)
}, a.buttons.confirm.callback = function () {
return a.callback.call(this, !0)
}, !b.isFunction(a.callback))throw new Error("confirm requires a callback");
return p.dialog(a)
}, p.prompt = function () {
var a, d, e, f, h, i, k;
if (f = b(n.form), d = {
className: "bootbox-prompt",
buttons: l("cancel", "confirm"),
value: "",
inputType: "text"
}, a = m(j(d, arguments, ["title", "callback"]), ["cancel", "confirm"]), i = a.show === c ? !0 : a.show, a.message = f, a.buttons.cancel.callback = a.onEscape = function () {
return a.callback.call(this, null)
}, a.buttons.confirm.callback = function () {
var c;
switch (a.inputType) {
case"text":
case"textarea":
case"email":
case"select":
case"date":
case"time":
case"number":
case"password":
c = h.val();
break;
case"checkbox":
var d = h.find("input:checked");
c = [], g(d, function (a, d) {
c.push(b(d).val())
})
}
return a.callback.call(this, c)
}, a.show = !1, !a.title)throw new Error("prompt requires a title");
if (!b.isFunction(a.callback))throw new Error("prompt requires a callback");
if (!n.inputs[a.inputType])throw new Error("invalid prompt type");
switch (h = b(n.inputs[a.inputType]), a.inputType) {
case"text":
case"textarea":
case"email":
case"date":
case"time":
case"number":
case"password":
h.val(a.value);
break;
case"select":
var o = {};
if (k = a.inputOptions || [], !b.isArray(k))throw new Error("Please pass an array of input options");
if (!k.length)throw new Error("prompt with select requires options");
g(k, function (a, d) {
var e = h;
if (d.value === c || d.text === c)throw new Error("given options in wrong format");
d.group && (o[d.group] || (o[d.group] = b("<optgroup/>").attr("label", d.group)), e = o[d.group]), e.append("<option value='" + d.value + "'>" + d.text + "</option>")
}), g(o, function (a, b) {
h.append(b)
}), h.val(a.value);
break;
case"checkbox":
var q = b.isArray(a.value) ? a.value : [a.value];
if (k = a.inputOptions || [], !k.length)throw new Error("prompt with checkbox requires options");
if (!k[0].value || !k[0].text)throw new Error("given options in wrong format");
h = b("<div/>"), g(k, function (c, d) {
var e = b(n.inputs[a.inputType]);
e.find("input").attr("value", d.value), e.find("label").append(d.text), g(q, function (a, b) {
b === d.value && e.find("input").prop("checked", !0)
}), h.append(e)
})
}
return a.placeholder && h.attr("placeholder", a.placeholder), a.pattern && h.attr("pattern", a.pattern), a.maxlength && h.attr("maxlength", a.maxlength), f.append(h), f.on("submit", function (a) {
a.preventDefault(), a.stopPropagation(), e.find(".btn-primary").click()
}), e = p.dialog(a), e.off("shown.bs.modal"), e.on("shown.bs.modal", function () {
h.focus()
}), i === !0 && e.modal("show"), e
}, p.dialog = function (a) {
a = h(a);
var d = b(n.dialog), f = d.find(".modal-dialog"), i = d.find(".modal-body"), j = a.buttons, k = "", l = {onEscape: a.onEscape};
if (b.fn.modal === c)throw new Error("$.fn.modal is not defined; please double check you have included the Bootstrap JavaScript library. See http://getbootstrap.com/javascript/ for more details.");
if (g(j, function (a, b) {
k += "<button data-bb-handler='" + a + "' type='button' class='btn " + b.className + "'>" + b.label + "</button>&emsp;", l[a] = b.callback
}), i.find(".bootbox-body").html(a.message), a.animate === !0 && d.addClass("fade"), a.className && d.addClass(a.className), "large" === a.size ? f.addClass("modal-lg") : "small" === a.size && f.addClass("modal-sm"), a.title && i.before(n.header), a.closeButton) {
var m = b(n.closeButton);
a.title ? d.find(".modal-header").prepend(m) : m.css("margin-top", "-10px").prependTo(i)
}
return a.title && d.find(".modal-title").html(a.title), k.length && (i.after(n.footer), d.find(".modal-footer").html(k)), d.on("hidden.bs.modal", function (a) {
a.target === this && d.remove()
}), d.on("shown.bs.modal", function () {
d.find(".btn-primary:first").focus()
}), "static" !== a.backdrop && d.on("click.dismiss.bs.modal", function (a) {
d.children(".modal-backdrop").length && (a.currentTarget = d.children(".modal-backdrop").get(0)), a.target === a.currentTarget && d.trigger("escape.close.bb")
}), d.on("escape.close.bb", function (a) {
l.onEscape && e(a, d, l.onEscape)
}), d.on("click", ".modal-footer button", function (a) {
var c = b(this).data("bb-handler");
e(a, d, l[c])
}), d.on("click", ".bootbox-close-button", function (a) {
e(a, d, l.onEscape)
}), d.on("keyup", function (a) {
27 === a.which && d.trigger("escape.close.bb")
}), b(a.container).append(d), d.modal({
backdrop: a.backdrop ? "static" : !1,
keyboard: !1,
show: !1
}), a.show && d.modal("show"), d
}, p.setDefaults = function () {
var a = {};
2 === arguments.length ? a[arguments[0]] = arguments[1] : a = arguments[0], b.extend(o, a)
}, p.hideAll = function () {
return b(".bootbox").modal("hide"), p
};
var q = {
bg_BG: {OK: "Ок", CANCEL: "Отказ", CONFIRM: "Потвърждавам"},
br: {OK: "OK", CANCEL: "Cancelar", CONFIRM: "Sim"},
cs: {OK: "OK", CANCEL: "Zrušit", CONFIRM: "Potvrdit"},
da: {OK: "OK", CANCEL: "Annuller", CONFIRM: "Accepter"},
de: {OK: "OK", CANCEL: "Abbrechen", CONFIRM: "Akzeptieren"},
el: {OK: "Εντάξει", CANCEL: "Ακύρωση", CONFIRM: "Επιβεβαίωση"},
en: {OK: "OK", CANCEL: "Cancel", CONFIRM: "OK"},
es: {OK: "OK", CANCEL: "Cancelar", CONFIRM: "Aceptar"},
et: {OK: "OK", CANCEL: "Katkesta", CONFIRM: "OK"},
fa: {OK: "قبول", CANCEL: "لغو", CONFIRM: "تایید"},
fi: {OK: "OK", CANCEL: "Peruuta", CONFIRM: "OK"},
fr: {OK: "OK", CANCEL: "Annuler", CONFIRM: "D'accord"},
he: {OK: "אישור", CANCEL: "ביטול", CONFIRM: "אישור"},
hu: {OK: "OK", CANCEL: "Mégsem", CONFIRM: "Megerősít"},
hr: {OK: "OK", CANCEL: "Odustani", CONFIRM: "Potvrdi"},
id: {OK: "OK", CANCEL: "Batal", CONFIRM: "OK"},
it: {OK: "OK", CANCEL: "Annulla", CONFIRM: "Conferma"},
ja: {OK: "OK", CANCEL: "キャンセル", CONFIRM: "確認"},
lt: {OK: "Gerai", CANCEL: "Atšaukti", CONFIRM: "Patvirtinti"},
lv: {OK: "Labi", CANCEL: "Atcelt", CONFIRM: "Apstiprināt"},
nl: {OK: "OK", CANCEL: "Annuleren", CONFIRM: "Accepteren"},
no: {OK: "OK", CANCEL: "Avbryt", CONFIRM: "OK"},
pl: {OK: "OK", CANCEL: "Anuluj", CONFIRM: "Potwierdź"},
pt: {OK: "OK", CANCEL: "Cancelar", CONFIRM: "Confirmar"},
ru: {OK: "OK", CANCEL: "Отмена", CONFIRM: "Применить"},
sq: {OK: "OK", CANCEL: "Anulo", CONFIRM: "Prano"},
sv: {OK: "OK", CANCEL: "Avbryt", CONFIRM: "OK"},
th: {OK: "ตกลง", CANCEL: "ยกเลิก", CONFIRM: "ยืนยัน"},
tr: {OK: "Tamam", CANCEL: "İptal", CONFIRM: "Onayla"},
zh_CN: {OK: "确定", CANCEL: "取消", CONFIRM: "确认"},
zh_TW: {OK: "OK", CANCEL: "取消", CONFIRM: "確認"}
};
return p.addLocale = function (a, c) {
return b.each(["OK", "CANCEL", "CONFIRM"], function (a, b) {
if (!c[b])throw new Error("Please supply a translation for '" + b + "'")
}), q[a] = {OK: c.OK, CANCEL: c.CANCEL, CONFIRM: c.CONFIRM}, p
}, p.removeLocale = function (a) {
return delete q[a], p
}, p.setLocale = function (a) {
return p.setDefaults("locale", a)
}, p.init = function (c) {
return a(c || b)
}, p
});
#loading-bar,#loading-bar-spinner{pointer-events:none;-webkit-pointer-events:none;-webkit-transition:350ms linear all;-moz-transition:350ms linear all;-o-transition:350ms linear all;transition:350ms linear all}#loading-bar-spinner.ng-enter,#loading-bar-spinner.ng-leave.ng-leave-active,#loading-bar.ng-enter,#loading-bar.ng-leave.ng-leave-active{opacity:0}#loading-bar-spinner.ng-enter.ng-enter-active,#loading-bar-spinner.ng-leave,#loading-bar.ng-enter.ng-enter-active,#loading-bar.ng-leave{opacity:1}#loading-bar .bar{-webkit-transition:width 350ms;-moz-transition:width 350ms;-o-transition:width 350ms;transition:width 350ms;background:#29d;position:fixed;z-index:10002;top:0;left:0;width:100%;height:2px;border-bottom-right-radius:1px;border-top-right-radius:1px}#loading-bar .peg{position:absolute;width:70px;right:0;top:0;height:2px;opacity:.45;-moz-box-shadow:#29d 1px 0 6px 1px;-ms-box-shadow:#29d 1px 0 6px 1px;-webkit-box-shadow:#29d 1px 0 6px 1px;box-shadow:#29d 1px 0 6px 1px;-moz-border-radius:100%;-webkit-border-radius:100%;border-radius:100%}#loading-bar-spinner{display:block;position:fixed;z-index:10002;top:10px;left:10px}#loading-bar-spinner .spinner-icon{width:14px;height:14px;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:loading-bar-spinner 400ms linear infinite;-moz-animation:loading-bar-spinner 400ms linear infinite;-ms-animation:loading-bar-spinner 400ms linear infinite;-o-animation:loading-bar-spinner 400ms linear infinite;animation:loading-bar-spinner 400ms linear infinite}@-webkit-keyframes loading-bar-spinner{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-moz-keyframes loading-bar-spinner{0%{-moz-transform:rotate(0);transform:rotate(0)}100%{-moz-transform:rotate(360deg);transform:rotate(360deg)}}@-o-keyframes loading-bar-spinner{0%{-o-transform:rotate(0);transform:rotate(0)}100%{-o-transform:rotate(360deg);transform:rotate(360deg)}}@-ms-keyframes loading-bar-spinner{0%{-ms-transform:rotate(0);transform:rotate(0)}100%{-ms-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes loading-bar-spinner{0%{transform:rotate(0)}100%{transform:rotate(360deg)}} #loading-bar, #loading-bar-spinner {
\ No newline at end of file pointer-events: none;
-webkit-pointer-events: none;
-webkit-transition: 350ms linear all;
-moz-transition: 350ms linear all;
-o-transition: 350ms linear all;
transition: 350ms linear all
}
#loading-bar-spinner.ng-enter, #loading-bar-spinner.ng-leave.ng-leave-active, #loading-bar.ng-enter, #loading-bar.ng-leave.ng-leave-active {
opacity: 0
}
#loading-bar-spinner.ng-enter.ng-enter-active, #loading-bar-spinner.ng-leave, #loading-bar.ng-enter.ng-enter-active, #loading-bar.ng-leave {
opacity: 1
}
#loading-bar .bar {
-webkit-transition: width 350ms;
-moz-transition: width 350ms;
-o-transition: width 350ms;
transition: width 350ms;
background: #29d;
position: fixed;
z-index: 10002;
top: 0;
left: 0;
width: 100%;
height: 2px;
border-bottom-right-radius: 1px;
border-top-right-radius: 1px
}
#loading-bar .peg {
position: absolute;
width: 70px;
right: 0;
top: 0;
height: 2px;
opacity: .45;
-moz-box-shadow: #29d 1px 0 6px 1px;
-ms-box-shadow: #29d 1px 0 6px 1px;
-webkit-box-shadow: #29d 1px 0 6px 1px;
box-shadow: #29d 1px 0 6px 1px;
-moz-border-radius: 100%;
-webkit-border-radius: 100%;
border-radius: 100%
}
#loading-bar-spinner {
display: block;
position: fixed;
z-index: 10002;
top: 10px;
left: 10px
}
#loading-bar-spinner .spinner-icon {
width: 14px;
height: 14px;
border: 2px solid transparent;
border-top-color: #29d;
border-left-color: #29d;
border-radius: 50%;
-webkit-animation: loading-bar-spinner 400ms linear infinite;
-moz-animation: loading-bar-spinner 400ms linear infinite;
-ms-animation: loading-bar-spinner 400ms linear infinite;
-o-animation: loading-bar-spinner 400ms linear infinite;
animation: loading-bar-spinner 400ms linear infinite
}
@-webkit-keyframes loading-bar-spinner {
0% {
-webkit-transform: rotate(0);
transform: rotate(0)
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg)
}
}
@-moz-keyframes loading-bar-spinner {
0% {
-moz-transform: rotate(0);
transform: rotate(0)
}
100% {
-moz-transform: rotate(360deg);
transform: rotate(360deg)
}
}
@-o-keyframes loading-bar-spinner {
0% {
-o-transform: rotate(0);
transform: rotate(0)
}
100% {
-o-transform: rotate(360deg);
transform: rotate(360deg)
}
}
@-ms-keyframes loading-bar-spinner {
0% {
-ms-transform: rotate(0);
transform: rotate(0)
}
100% {
-ms-transform: rotate(360deg);
transform: rotate(360deg)
}
}
@keyframes loading-bar-spinner {
0% {
transform: rotate(0)
}
100% {
transform: rotate(360deg)
}
}
...@@ -4,4 +4,95 @@ ...@@ -4,4 +4,95 @@
* Copyright (c) 2015 Wes Cruver * Copyright (c) 2015 Wes Cruver
* License: MIT * License: MIT
*/ */
!function(){"use strict";angular.module("angular-loading-bar",["cfp.loadingBarInterceptor"]),angular.module("chieffancypants.loadingBar",["cfp.loadingBarInterceptor"]),angular.module("cfp.loadingBarInterceptor",["cfp.loadingBar"]).config(["$httpProvider",function(a){var b=["$q","$cacheFactory","$timeout","$rootScope","$log","cfpLoadingBar",function(b,c,d,e,f,g){function h(){d.cancel(j),g.complete(),l=0,k=0}function i(b){var d,e=c.get("$http"),f=a.defaults;!b.cache&&!f.cache||b.cache===!1||"GET"!==b.method&&"JSONP"!==b.method||(d=angular.isObject(b.cache)?b.cache:angular.isObject(f.cache)?f.cache:e);var g=void 0!==d?void 0!==d.get(b.url):!1;return void 0!==b.cached&&g!==b.cached?b.cached:(b.cached=g,g)}var j,k=0,l=0,m=g.latencyThreshold;return{request:function(a){return a.ignoreLoadingBar||i(a)||(e.$broadcast("cfpLoadingBar:loading",{url:a.url}),0===k&&(j=d(function(){g.start()},m)),k++,g.set(l/k)),a},response:function(a){return a&&a.config?(a.config.ignoreLoadingBar||i(a.config)||(l++,e.$broadcast("cfpLoadingBar:loaded",{url:a.config.url,result:a}),l>=k?h():g.set(l/k)),a):(f.error("Broken interceptor detected: Config object not supplied in response:\n https://github.com/chieffancypants/angular-loading-bar/pull/50"),a)},responseError:function(a){return a&&a.config?(a.config.ignoreLoadingBar||i(a.config)||(l++,e.$broadcast("cfpLoadingBar:loaded",{url:a.config.url,result:a}),l>=k?h():g.set(l/k)),b.reject(a)):(f.error("Broken interceptor detected: Config object not supplied in rejection:\n https://github.com/chieffancypants/angular-loading-bar/pull/50"),b.reject(a))}}}];a.interceptors.push(b)}]),angular.module("cfp.loadingBar",[]).provider("cfpLoadingBar",function(){this.autoIncrement=!0,this.includeSpinner=!0,this.includeBar=!0,this.latencyThreshold=100,this.startSize=.02,this.parentSelector="body",this.spinnerTemplate='<div id="loading-bar-spinner"><div class="spinner-icon"></div></div>',this.loadingBarTemplate='<div id="loading-bar"><div class="bar"><div class="peg"></div></div></div>',this.$get=["$injector","$document","$timeout","$rootScope",function(a,b,c,d){function e(){k||(k=a.get("$animate"));var e=b.find(n).eq(0);c.cancel(m),r||(d.$broadcast("cfpLoadingBar:started"),r=!0,v&&k.enter(o,e,angular.element(e[0].lastChild)),u&&k.enter(q,e,angular.element(e[0].lastChild)),f(w))}function f(a){if(r){var b=100*a+"%";p.css("width",b),s=a,t&&(c.cancel(l),l=c(function(){g()},250))}}function g(){if(!(h()>=1)){var a=0,b=h();a=b>=0&&.25>b?(3*Math.random()+3)/100:b>=.25&&.65>b?3*Math.random()/100:b>=.65&&.9>b?2*Math.random()/100:b>=.9&&.99>b?.005:0;var c=h()+a;f(c)}}function h(){return s}function i(){s=0,r=!1}function j(){k||(k=a.get("$animate")),d.$broadcast("cfpLoadingBar:completed"),f(1),c.cancel(m),m=c(function(){var a=k.leave(o,i);a&&a.then&&a.then(i),k.leave(q)},500)}var k,l,m,n=this.parentSelector,o=angular.element(this.loadingBarTemplate),p=o.find("div").eq(0),q=angular.element(this.spinnerTemplate),r=!1,s=0,t=this.autoIncrement,u=this.includeSpinner,v=this.includeBar,w=this.startSize;return{start:e,set:f,status:h,inc:g,complete:j,autoIncrement:this.autoIncrement,includeSpinner:this.includeSpinner,latencyThreshold:this.latencyThreshold,parentSelector:this.parentSelector,startSize:this.startSize}}]})}(); !function () {
\ No newline at end of file "use strict";
angular.module("angular-loading-bar", ["cfp.loadingBarInterceptor"]), angular.module("chieffancypants.loadingBar", ["cfp.loadingBarInterceptor"]), angular.module("cfp.loadingBarInterceptor", ["cfp.loadingBar"]).config(["$httpProvider", function (a) {
var b = ["$q", "$cacheFactory", "$timeout", "$rootScope", "$log", "cfpLoadingBar", function (b, c, d, e, f, g) {
function h() {
d.cancel(j), g.complete(), l = 0, k = 0
}
function i(b) {
var d, e = c.get("$http"), f = a.defaults;
!b.cache && !f.cache || b.cache === !1 || "GET" !== b.method && "JSONP" !== b.method || (d = angular.isObject(b.cache) ? b.cache : angular.isObject(f.cache) ? f.cache : e);
var g = void 0 !== d ? void 0 !== d.get(b.url) : !1;
return void 0 !== b.cached && g !== b.cached ? b.cached : (b.cached = g, g)
}
var j, k = 0, l = 0, m = g.latencyThreshold;
return {
request: function (a) {
return a.ignoreLoadingBar || i(a) || (e.$broadcast("cfpLoadingBar:loading", {url: a.url}), 0 === k && (j = d(function () {
g.start()
}, m)), k++, g.set(l / k)), a
}, response: function (a) {
return a && a.config ? (a.config.ignoreLoadingBar || i(a.config) || (l++, e.$broadcast("cfpLoadingBar:loaded", {
url: a.config.url,
result: a
}), l >= k ? h() : g.set(l / k)), a) : (f.error("Broken interceptor detected: Config object not supplied in response:\n https://github.com/chieffancypants/angular-loading-bar/pull/50"), a)
}, responseError: function (a) {
return a && a.config ? (a.config.ignoreLoadingBar || i(a.config) || (l++, e.$broadcast("cfpLoadingBar:loaded", {
url: a.config.url,
result: a
}), l >= k ? h() : g.set(l / k)), b.reject(a)) : (f.error("Broken interceptor detected: Config object not supplied in rejection:\n https://github.com/chieffancypants/angular-loading-bar/pull/50"), b.reject(a))
}
}
}];
a.interceptors.push(b)
}]), angular.module("cfp.loadingBar", []).provider("cfpLoadingBar", function () {
this.autoIncrement = !0, this.includeSpinner = !0, this.includeBar = !0, this.latencyThreshold = 100, this.startSize = .02, this.parentSelector = "body", this.spinnerTemplate = '<div id="loading-bar-spinner"><div class="spinner-icon"></div></div>', this.loadingBarTemplate = '<div id="loading-bar"><div class="bar"><div class="peg"></div></div></div>', this.$get = ["$injector", "$document", "$timeout", "$rootScope", function (a, b, c, d) {
function e() {
k || (k = a.get("$animate"));
var e = b.find(n).eq(0);
c.cancel(m), r || (d.$broadcast("cfpLoadingBar:started"), r = !0, v && k.enter(o, e, angular.element(e[0].lastChild)), u && k.enter(q, e, angular.element(e[0].lastChild)), f(w))
}
function f(a) {
if (r) {
var b = 100 * a + "%";
p.css("width", b), s = a, t && (c.cancel(l), l = c(function () {
g()
}, 250))
}
}
function g() {
if (!(h() >= 1)) {
var a = 0, b = h();
a = b >= 0 && .25 > b ? (3 * Math.random() + 3) / 100 : b >= .25 && .65 > b ? 3 * Math.random() / 100 : b >= .65 && .9 > b ? 2 * Math.random() / 100 : b >= .9 && .99 > b ? .005 : 0;
var c = h() + a;
f(c)
}
}
function h() {
return s
}
function i() {
s = 0, r = !1
}
function j() {
k || (k = a.get("$animate")), d.$broadcast("cfpLoadingBar:completed"), f(1), c.cancel(m), m = c(function () {
var a = k.leave(o, i);
a && a.then && a.then(i), k.leave(q)
}, 500)
}
var k, l, m, n = this.parentSelector, o = angular.element(this.loadingBarTemplate), p = o.find("div").eq(0), q = angular.element(this.spinnerTemplate), r = !1, s = 0, t = this.autoIncrement, u = this.includeSpinner, v = this.includeBar, w = this.startSize;
return {
start: e,
set: f,
status: h,
inc: g,
complete: j,
autoIncrement: this.autoIncrement,
includeSpinner: this.includeSpinner,
latencyThreshold: this.latencyThreshold,
parentSelector: this.parentSelector,
startSize: this.startSize
}
}]
})
}();
/** /**
* @version 2.0.2 * @version 2.0.2
* @license MIT * @license MIT
*/ */
!function(t,e){"use strict";t.module("smart-table",[]).run(["$templateCache",function(t){t.put("template/smart-table/pagination.html",'<nav ng-if="pages.length >= 2"><ul class="pagination"><li ng-repeat="page in pages" ng-class="{active: page==currentPage}"><a ng-click="selectPage(page)">{{page}}</a></li></ul></nav>')}]),t.module("smart-table").constant("stConfig",{pagination:{template:"template/smart-table/pagination.html",itemsByPage:10,displayedPages:5},search:{delay:400},select:{mode:"single",selectedClass:"st-selected"},sort:{ascentClass:"st-sort-ascent",descentClass:"st-sort-descent"},pipe:{delay:100}}),t.module("smart-table").controller("stTableController",["$scope","$parse","$filter","$attrs",function(a,s,n,r){function i(t){return t?[].concat(t):[]}function c(){h=i(l(a)),P===!0&&S.pipe()}var l,o,u,p=r.stTable,g=s(p),f=g.assign,d=n("orderBy"),m=n("filter"),h=i(g(a)),b={sort:{},search:{},pagination:{start:0}},P=!0,S=this;r.stSafeSrc&&(l=s(r.stSafeSrc),a.$watch(function(){var t=l(a);return t?t.length:0},function(t){t!==h.length&&c()}),a.$watch(function(){return l(a)},function(t,e){t!==e&&c()})),this.sortBy=function(e,a){return b.sort.predicate=e,b.sort.reverse=a===!0,t.isFunction(e)?b.sort.functionName=e.name:delete b.sort.functionName,b.pagination.start=0,this.pipe()},this.search=function(e,a){var s=b.search.predicateObject||{},n=a?a:"$";return e=t.isString(e)?e.trim():e,s[n]=e,e||delete s[n],b.search.predicateObject=s,b.pagination.start=0,this.pipe()},this.pipe=function(){var t,s=b.pagination;o=b.search.predicateObject?m(h,b.search.predicateObject):h,b.sort.predicate&&(o=d(o,b.sort.predicate,b.sort.reverse)),s.number!==e&&(s.numberOfPages=o.length>0?Math.ceil(o.length/s.number):1,s.start=s.start>=o.length?(s.numberOfPages-1)*s.number:s.start,t=o.slice(s.start,s.start+parseInt(s.number))),f(a,t||o)},this.select=function(t,a){var s=h,n=s.indexOf(t);-1!==n&&("single"===a?(t.isSelected=t.isSelected!==!0,u&&(u.isSelected=!1),u=t.isSelected===!0?t:e):s[n].isSelected=!s[n].isSelected)},this.slice=function(t,e){return b.pagination.start=t,b.pagination.number=e,this.pipe()},this.tableState=function(){return b},this.getFilteredCollection=function(){return o||h},this.setFilterFunction=function(t){m=n(t)},this.setSortFunction=function(t){d=n(t)},this.preventPipeOnWatch=function(){P=!1}}]).directive("stTable",function(){return{restrict:"A",controller:"stTableController",link:function(t,e,a,s){a.stSetFilter&&s.setFilterFunction(a.stSetFilter),a.stSetSort&&s.setSortFunction(a.stSetSort)}}}),t.module("smart-table").directive("stSearch",["stConfig","$timeout",function(t,e){return{require:"^stTable",link:function(a,s,n,r){var i=r,c=null,l=n.stDelay||t.search.delay;n.$observe("stSearch",function(t,e){var a=s[0].value;t!==e&&a&&(r.tableState().search={},i.search(a,t))}),a.$watch(function(){return r.tableState().search},function(t){var e=n.stSearch||"$";t.predicateObject&&t.predicateObject[e]!==s[0].value&&(s[0].value=t.predicateObject[e]||"")},!0),s.bind("input",function(t){t=t.originalEvent||t,null!==c&&e.cancel(c),c=e(function(){i.search(t.target.value,n.stSearch||""),c=null},l)})}}}]),t.module("smart-table").directive("stSelectRow",["stConfig",function(t){return{restrict:"A",require:"^stTable",scope:{row:"=stSelectRow"},link:function(e,a,s,n){var r=s.stSelectMode||t.select.mode;a.bind("click",function(){e.$apply(function(){n.select(e.row,r)})}),e.$watch("row.isSelected",function(e){e===!0?a.addClass(t.select.selectedClass):a.removeClass(t.select.selectedClass)})}}}]),t.module("smart-table").directive("stSort",["stConfig","$parse",function(a,s){return{restrict:"A",require:"^stTable",link:function(n,r,i,c){function l(){g++,u=t.isFunction(p(n))?p(n):i.stSort,g%3===0&&i.stSkipNatural===e?(g=0,c.tableState().sort={},c.tableState().pagination.start=0,c.pipe()):c.sortBy(u,g%2===0)}var o,u=i.stSort,p=s(u),g=0,f=i.stClassAscent||a.sort.ascentClass,d=i.stClassDescent||a.sort.descentClass,m=[f,d];i.stSortDefault&&(o=n.$eval(i.stSortDefault)!==e?n.$eval(i.stSortDefault):i.stSortDefault),r.bind("click",function(){u&&n.$apply(l)}),o&&(g="reverse"===o?1:0,l()),n.$watch(function(){return c.tableState().sort},function(t){t.predicate!==u?(g=0,r.removeClass(f).removeClass(d)):(g=t.reverse===!0?2:1,r.removeClass(m[g%2]).addClass(m[g-1]))},!0)}}}]),t.module("smart-table").directive("stPagination",["stConfig",function(t){return{restrict:"EA",require:"^stTable",scope:{stItemsByPage:"=?",stDisplayedPages:"=?",stPageChange:"&"},templateUrl:function(e,a){return a.stTemplate?a.stTemplate:t.pagination.template},link:function(e,a,s,n){function r(){var t,a,s=n.tableState().pagination,r=1,i=e.currentPage;for(e.currentPage=Math.floor(s.start/s.number)+1,r=Math.max(r,e.currentPage-Math.abs(Math.floor(e.stDisplayedPages/2))),t=r+e.stDisplayedPages,t>s.numberOfPages&&(t=s.numberOfPages+1,r=Math.max(1,t-e.stDisplayedPages)),e.pages=[],e.numPages=s.numberOfPages,a=r;t>a;a++)e.pages.push(a);i!==e.currentPage&&e.stPageChange({newPage:e.currentPage})}e.stItemsByPage=e.stItemsByPage?+e.stItemsByPage:t.pagination.itemsByPage,e.stDisplayedPages=e.stDisplayedPages?+e.stDisplayedPages:t.pagination.displayedPages,e.currentPage=1,e.pages=[],e.$watch(function(){return n.tableState().pagination},r,!0),e.$watch("stItemsByPage",function(t,a){t!==a&&e.selectPage(1)}),e.$watch("stDisplayedPages",r),e.selectPage=function(t){t>0&&t<=e.numPages&&n.slice((t-1)*e.stItemsByPage,e.stItemsByPage)},n.tableState().pagination.number||n.slice(0,e.stItemsByPage)}}}]),t.module("smart-table").directive("stPipe",["stConfig","$timeout",function(e,a){return{require:"stTable",scope:{stPipe:"="},link:{pre:function(s,n,r,i){var c=null;t.isFunction(s.stPipe)&&(i.preventPipeOnWatch(),i.pipe=function(){return null!==c&&a.cancel(c),c=a(function(){s.stPipe(i.tableState(),i)},e.pipe.delay)})},post:function(t,e,a,s){s.pipe()}}}}])}(angular); !function (t, e) {
\ No newline at end of file "use strict";
t.module("smart-table", []).run(["$templateCache", function (t) {
t.put("template/smart-table/pagination.html", '<nav ng-if="pages.length >= 2"><ul class="pagination"><li ng-repeat="page in pages" ng-class="{active: page==currentPage}"><a ng-click="selectPage(page)">{{page}}</a></li></ul></nav>')
}]), t.module("smart-table").constant("stConfig", {
pagination: {
template: "template/smart-table/pagination.html",
itemsByPage: 10,
displayedPages: 5
},
search: {delay: 400},
select: {mode: "single", selectedClass: "st-selected"},
sort: {ascentClass: "st-sort-ascent", descentClass: "st-sort-descent"},
pipe: {delay: 100}
}), t.module("smart-table").controller("stTableController", ["$scope", "$parse", "$filter", "$attrs", function (a, s, n, r) {
function i(t) {
return t ? [].concat(t) : []
}
function c() {
h = i(l(a)), P === !0 && S.pipe()
}
var l, o, u, p = r.stTable, g = s(p), f = g.assign, d = n("orderBy"), m = n("filter"), h = i(g(a)), b = {
sort: {},
search: {},
pagination: {start: 0}
}, P = !0, S = this;
r.stSafeSrc && (l = s(r.stSafeSrc), a.$watch(function () {
var t = l(a);
return t ? t.length : 0
}, function (t) {
t !== h.length && c()
}), a.$watch(function () {
return l(a)
}, function (t, e) {
t !== e && c()
})), this.sortBy = function (e, a) {
return b.sort.predicate = e, b.sort.reverse = a === !0, t.isFunction(e) ? b.sort.functionName = e.name : delete b.sort.functionName, b.pagination.start = 0, this.pipe()
}, this.search = function (e, a) {
var s = b.search.predicateObject || {}, n = a ? a : "$";
return e = t.isString(e) ? e.trim() : e, s[n] = e, e || delete s[n], b.search.predicateObject = s, b.pagination.start = 0, this.pipe()
}, this.pipe = function () {
var t, s = b.pagination;
o = b.search.predicateObject ? m(h, b.search.predicateObject) : h, b.sort.predicate && (o = d(o, b.sort.predicate, b.sort.reverse)), s.number !== e && (s.numberOfPages = o.length > 0 ? Math.ceil(o.length / s.number) : 1, s.start = s.start >= o.length ? (s.numberOfPages - 1) * s.number : s.start, t = o.slice(s.start, s.start + parseInt(s.number))), f(a, t || o)
}, this.select = function (t, a) {
var s = h, n = s.indexOf(t);
-1 !== n && ("single" === a ? (t.isSelected = t.isSelected !== !0, u && (u.isSelected = !1), u = t.isSelected === !0 ? t : e) : s[n].isSelected = !s[n].isSelected)
}, this.slice = function (t, e) {
return b.pagination.start = t, b.pagination.number = e, this.pipe()
}, this.tableState = function () {
return b
}, this.getFilteredCollection = function () {
return o || h
}, this.setFilterFunction = function (t) {
m = n(t)
}, this.setSortFunction = function (t) {
d = n(t)
}, this.preventPipeOnWatch = function () {
P = !1
}
}]).directive("stTable", function () {
return {
restrict: "A", controller: "stTableController", link: function (t, e, a, s) {
a.stSetFilter && s.setFilterFunction(a.stSetFilter), a.stSetSort && s.setSortFunction(a.stSetSort)
}
}
}), t.module("smart-table").directive("stSearch", ["stConfig", "$timeout", function (t, e) {
return {
require: "^stTable", link: function (a, s, n, r) {
var i = r, c = null, l = n.stDelay || t.search.delay;
n.$observe("stSearch", function (t, e) {
var a = s[0].value;
t !== e && a && (r.tableState().search = {}, i.search(a, t))
}), a.$watch(function () {
return r.tableState().search
}, function (t) {
var e = n.stSearch || "$";
t.predicateObject && t.predicateObject[e] !== s[0].value && (s[0].value = t.predicateObject[e] || "")
}, !0), s.bind("input", function (t) {
t = t.originalEvent || t, null !== c && e.cancel(c), c = e(function () {
i.search(t.target.value, n.stSearch || ""), c = null
}, l)
})
}
}
}]), t.module("smart-table").directive("stSelectRow", ["stConfig", function (t) {
return {
restrict: "A", require: "^stTable", scope: {row: "=stSelectRow"}, link: function (e, a, s, n) {
var r = s.stSelectMode || t.select.mode;
a.bind("click", function () {
e.$apply(function () {
n.select(e.row, r)
})
}), e.$watch("row.isSelected", function (e) {
e === !0 ? a.addClass(t.select.selectedClass) : a.removeClass(t.select.selectedClass)
})
}
}
}]), t.module("smart-table").directive("stSort", ["stConfig", "$parse", function (a, s) {
return {
restrict: "A", require: "^stTable", link: function (n, r, i, c) {
function l() {
g++, u = t.isFunction(p(n)) ? p(n) : i.stSort, g % 3 === 0 && i.stSkipNatural === e ? (g = 0, c.tableState().sort = {}, c.tableState().pagination.start = 0, c.pipe()) : c.sortBy(u, g % 2 === 0)
}
var o, u = i.stSort, p = s(u), g = 0, f = i.stClassAscent || a.sort.ascentClass, d = i.stClassDescent || a.sort.descentClass, m = [f, d];
i.stSortDefault && (o = n.$eval(i.stSortDefault) !== e ? n.$eval(i.stSortDefault) : i.stSortDefault), r.bind("click", function () {
u && n.$apply(l)
}), o && (g = "reverse" === o ? 1 : 0, l()), n.$watch(function () {
return c.tableState().sort
}, function (t) {
t.predicate !== u ? (g = 0, r.removeClass(f).removeClass(d)) : (g = t.reverse === !0 ? 2 : 1, r.removeClass(m[g % 2]).addClass(m[g - 1]))
}, !0)
}
}
}]), t.module("smart-table").directive("stPagination", ["stConfig", function (t) {
return {
restrict: "EA",
require: "^stTable",
scope: {stItemsByPage: "=?", stDisplayedPages: "=?", stPageChange: "&"},
templateUrl: function (e, a) {
return a.stTemplate ? a.stTemplate : t.pagination.template
},
link: function (e, a, s, n) {
function r() {
var t, a, s = n.tableState().pagination, r = 1, i = e.currentPage;
for (e.currentPage = Math.floor(s.start / s.number) + 1, r = Math.max(r, e.currentPage - Math.abs(Math.floor(e.stDisplayedPages / 2))), t = r + e.stDisplayedPages, t > s.numberOfPages && (t = s.numberOfPages + 1, r = Math.max(1, t - e.stDisplayedPages)), e.pages = [], e.numPages = s.numberOfPages, a = r; t > a; a++)e.pages.push(a);
i !== e.currentPage && e.stPageChange({newPage: e.currentPage})
}
e.stItemsByPage = e.stItemsByPage ? +e.stItemsByPage : t.pagination.itemsByPage, e.stDisplayedPages = e.stDisplayedPages ? +e.stDisplayedPages : t.pagination.displayedPages, e.currentPage = 1, e.pages = [], e.$watch(function () {
return n.tableState().pagination
}, r, !0), e.$watch("stItemsByPage", function (t, a) {
t !== a && e.selectPage(1)
}), e.$watch("stDisplayedPages", r), e.selectPage = function (t) {
t > 0 && t <= e.numPages && n.slice((t - 1) * e.stItemsByPage, e.stItemsByPage)
}, n.tableState().pagination.number || n.slice(0, e.stItemsByPage)
}
}
}]), t.module("smart-table").directive("stPipe", ["stConfig", "$timeout", function (e, a) {
return {
require: "stTable", scope: {stPipe: "="}, link: {
pre: function (s, n, r, i) {
var c = null;
t.isFunction(s.stPipe) && (i.preventPipeOnWatch(), i.pipe = function () {
return null !== c && a.cancel(c), c = a(function () {
s.stPipe(i.tableState(), i)
}, e.pipe.delay)
})
}, post: function (t, e, a, s) {
s.pipe()
}
}
}
}])
}(angular);
This source diff could not be displayed because it is too large. You can view the blob instead.
/*! /*!
angular-xeditable - 0.1.8 angular-xeditable - 0.1.8
Edit-in-place for angular.js Edit-in-place for angular.js
Build date: 2014-01-10 Build date: 2014-01-10
*/ */
angular.module("xeditable",[]).value("editableOptions",{theme:"default",buttons:"right",blurElem:"cancel",blurForm:"ignore",activate:"focus"}),angular.module("xeditable").directive("editableBsdate",["editableDirectiveFactory",function(a){return a({directiveName:"editableBsdate",inputTpl:'<input type="text">'})}]),angular.module("xeditable").directive("editableBstime",["editableDirectiveFactory",function(a){return a({directiveName:"editableBstime",inputTpl:"<timepicker></timepicker>",render:function(){this.parent.render.call(this);var a=angular.element('<div class="well well-small" style="display:inline-block;"></div>');a.attr("ng-model",this.inputEl.attr("ng-model")),this.inputEl.removeAttr("ng-model"),this.attrs.eNgChange&&(a.attr("ng-change",this.inputEl.attr("ng-change")),this.inputEl.removeAttr("ng-change")),this.inputEl.wrap(a)}})}]),angular.module("xeditable").directive("editableCheckbox",["editableDirectiveFactory",function(a){return a({directiveName:"editableCheckbox",inputTpl:'<input type="checkbox">',render:function(){this.parent.render.call(this),this.attrs.eTitle&&(this.inputEl.wrap("<label></label>"),this.inputEl.after(angular.element("<span></span>").text(this.attrs.eTitle)))},autosubmit:function(){var a=this;a.inputEl.bind("change",function(){setTimeout(function(){a.scope.$apply(function(){a.scope.$form.$submit()})},500)})}})}]),angular.module("xeditable").directive("editableChecklist",["editableDirectiveFactory","editableNgOptionsParser",function(a,b){return a({directiveName:"editableChecklist",inputTpl:"<span></span>",useCopy:!0,render:function(){this.parent.render.call(this);var a=b(this.attrs.eNgOptions),c='<label ng-repeat="'+a.ngRepeat+'">'+'<input type="checkbox" checklist-model="$parent.$data" checklist-value="'+a.locals.valueFn+'">'+'<span ng-bind="'+a.locals.displayFn+'"></span></label>';this.inputEl.removeAttr("ng-model"),this.inputEl.removeAttr("ng-options"),this.inputEl.html(c)}})}]),function(){var a="text|email|tel|number|url|search|color|date|datetime|time|month|week".split("|");angular.forEach(a,function(a){var b="editable"+a.charAt(0).toUpperCase()+a.slice(1);angular.module("xeditable").directive(b,["editableDirectiveFactory",function(c){return c({directiveName:b,inputTpl:'<input type="'+a+'">'})}])}),angular.module("xeditable").directive("editableRange",["editableDirectiveFactory",function(a){return a({directiveName:"editableRange",inputTpl:'<input type="range" id="range" name="range">',render:function(){this.parent.render.call(this),this.inputEl.after("<output>{{$data}}</output>")}})}])}(),angular.module("xeditable").directive("editableRadiolist",["editableDirectiveFactory","editableNgOptionsParser",function(a,b){return a({directiveName:"editableRadiolist",inputTpl:"<span></span>",render:function(){this.parent.render.call(this);var a=b(this.attrs.eNgOptions),c='<label ng-repeat="'+a.ngRepeat+'">'+'<input type="radio" ng-model="$parent.$data" value="{{'+a.locals.valueFn+'}}">'+'<span ng-bind="'+a.locals.displayFn+'"></span></label>';this.inputEl.removeAttr("ng-model"),this.inputEl.removeAttr("ng-options"),this.inputEl.html(c)},autosubmit:function(){var a=this;a.inputEl.bind("change",function(){setTimeout(function(){a.scope.$apply(function(){a.scope.$form.$submit()})},500)})}})}]),angular.module("xeditable").directive("editableSelect",["editableDirectiveFactory",function(a){return a({directiveName:"editableSelect",inputTpl:"<select></select>",autosubmit:function(){var a=this;a.inputEl.bind("change",function(){a.scope.$apply(function(){a.scope.$form.$submit()})})}})}]),angular.module("xeditable").directive("editableTextarea",["editableDirectiveFactory",function(a){return a({directiveName:"editableTextarea",inputTpl:"<textarea></textarea>",addListeners:function(){var a=this;a.parent.addListeners.call(a),a.single&&"no"!==a.buttons&&a.autosubmit()},autosubmit:function(){var a=this;a.inputEl.bind("keydown",function(b){(b.ctrlKey||b.metaKey)&&13===b.keyCode&&a.scope.$apply(function(){a.scope.$form.$submit()})})}})}]),angular.module("xeditable").factory("editableController",["$q","editableUtils",function(a,b){function c(a,c,d,e,f,g,h,i,j){var k,l,m=this;m.scope=a,m.elem=d,m.attrs=c,m.inputEl=null,m.editorEl=null,m.single=!0,m.error="",m.theme=f[g.theme]||f["default"],m.parent={},m.inputTpl="",m.directiveName="",m.useCopy=!1,m.single=null,m.buttons="right",m.init=function(b){if(m.single=b,m.name=c.eName||c[m.directiveName],!c[m.directiveName])throw"You should provide value for `"+m.directiveName+"` in editable element!";k=e(c[m.directiveName]),m.buttons=m.single?m.attrs.buttons||g.buttons:"no",c.eName&&m.scope.$watch("$data",function(a){m.scope.$form.$data[c.eName]=a}),c.onshow&&(m.onshow=function(){return m.catchError(e(c.onshow)(a))}),c.onhide&&(m.onhide=function(){return e(c.onhide)(a)}),c.oncancel&&(m.oncancel=function(){return e(c.oncancel)(a)}),c.onbeforesave&&(m.onbeforesave=function(){return m.catchError(e(c.onbeforesave)(a))}),c.onaftersave&&(m.onaftersave=function(){return m.catchError(e(c.onaftersave)(a))}),a.$parent.$watch(c[m.directiveName],function(){m.handleEmpty()})},m.render=function(){var a=m.theme;m.inputEl=angular.element(m.inputTpl),m.controlsEl=angular.element(a.controlsTpl),m.controlsEl.append(m.inputEl),"no"!==m.buttons&&(m.buttonsEl=angular.element(a.buttonsTpl),m.submitEl=angular.element(a.submitTpl),m.cancelEl=angular.element(a.cancelTpl),m.buttonsEl.append(m.submitEl).append(m.cancelEl),m.controlsEl.append(m.buttonsEl),m.inputEl.addClass("editable-has-buttons")),m.errorEl=angular.element(a.errorTpl),m.controlsEl.append(m.errorEl),m.editorEl=angular.element(m.single?a.formTpl:a.noformTpl),m.editorEl.append(m.controlsEl);for(var d in c.$attr)if(!(d.length<=1)){var e=!1,f=d.substring(1,2);if("e"===d.substring(0,1)&&f===f.toUpperCase()&&(e=d.substring(1),"Form"!==e&&"NgSubmit"!==e)){e=e.substring(0,1).toLowerCase()+b.camelToDash(e.substring(1));var h=""===c[d]?e:c[d];m.inputEl.attr(e,h)}}m.inputEl.addClass("editable-input"),m.inputEl.attr("ng-model","$data"),m.editorEl.addClass(b.camelToDash(m.directiveName)),m.single&&(m.editorEl.attr("editable-form","$form"),m.editorEl.attr("blur",m.attrs.blur||("no"===m.buttons?"cancel":g.blurElem))),angular.isFunction(a.postrender)&&a.postrender.call(m)},m.setLocalValue=function(){m.scope.$data=m.useCopy?angular.copy(k(a.$parent)):k(a.$parent)},m.show=function(){return m.setLocalValue(),m.render(),d.after(m.editorEl),i(m.editorEl)(a),m.addListeners(),d.addClass("editable-hide"),m.onshow()},m.hide=function(){return m.editorEl.remove(),d.removeClass("editable-hide"),m.onhide()},m.cancel=function(){m.oncancel()},m.addListeners=function(){m.inputEl.bind("keyup",function(a){if(m.single)switch(a.keyCode){case 27:m.scope.$apply(function(){m.scope.$form.$cancel()})}}),m.single&&"no"===m.buttons&&m.autosubmit(),m.editorEl.bind("click",function(a){1===a.which&&m.scope.$form.$visible&&(m.scope.$form._clicked=!0)})},m.setWaiting=function(a){a?(l=!m.inputEl.attr("disabled")&&!m.inputEl.attr("ng-disabled")&&!m.inputEl.attr("ng-enabled"),l&&(m.inputEl.attr("disabled","disabled"),m.buttonsEl&&m.buttonsEl.find("button").attr("disabled","disabled"))):l&&(m.inputEl.removeAttr("disabled"),m.buttonsEl&&m.buttonsEl.find("button").removeAttr("disabled"))},m.activate=function(){setTimeout(function(){var a=m.inputEl[0];"focus"===g.activate&&a.focus&&a.focus(),"select"===g.activate&&a.select&&a.select()},0)},m.setError=function(b){angular.isObject(b)||(a.$error=b,m.error=b)},m.catchError=function(a,b){return angular.isObject(a)&&b!==!0?j.when(a).then(angular.bind(this,function(a){this.catchError(a,!0)}),angular.bind(this,function(a){this.catchError(a,!0)})):b&&angular.isObject(a)&&a.status&&200!==a.status&&a.data&&angular.isString(a.data)?(this.setError(a.data),a=a.data):angular.isString(a)&&this.setError(a),a},m.save=function(){k.assign(a.$parent,angular.copy(m.scope.$data))},m.handleEmpty=function(){var b=k(a.$parent),c=null===b||void 0===b||""===b||angular.isArray(b)&&0===b.length;d.toggleClass("editable-empty",c)},m.autosubmit=angular.noop,m.onshow=angular.noop,m.onhide=angular.noop,m.oncancel=angular.noop,m.onbeforesave=angular.noop,m.onaftersave=angular.noop}return c.$inject=["$scope","$attrs","$element","$parse","editableThemes","editableOptions","$rootScope","$compile","$q"],c}]),angular.module("xeditable").factory("editableDirectiveFactory",["$parse","$compile","editableThemes","$rootScope","$document","editableController","editableFormController",function(a,b,c,d,e,f,g){return function(b){return{restrict:"A",scope:!0,require:[b.directiveName,"?^form"],controller:f,link:function(c,f,h,i){var j,k=i[0],l=!1;if(i[1])j=i[1],l=!0;else if(h.eForm){var m=a(h.eForm)(c);if(m)j=m,l=!0;else for(var n=0;n<e[0].forms.length;n++)if(e[0].forms[n].name===h.eForm){j=null,l=!0;break}}if(angular.forEach(b,function(a,b){void 0!==k[b]&&(k.parent[b]=k[b])}),angular.extend(k,b),k.init(!l),c.$editable=k,f.addClass("editable"),l)if(j){if(c.$form=j,!c.$form.$addEditable)throw"Form with editable elements should have `editable-form` attribute.";c.$form.$addEditable(k)}else d.$$editableBuffer=d.$$editableBuffer||{},d.$$editableBuffer[h.eForm]=d.$$editableBuffer[h.eForm]||[],d.$$editableBuffer[h.eForm].push(k),c.$form=null;else c.$form=g(),c.$form.$addEditable(k),h.eForm&&(c.$parent[h.eForm]=c.$form),h.eForm||(f.addClass("editable-click"),f.bind("click",function(a){a.preventDefault(),a.editable=k,c.$apply(function(){c.$form.$show()})}))}}}}]),angular.module("xeditable").factory("editableFormController",["$parse","$document","$rootScope","editablePromiseCollection","editableUtils",function(a,b,c,d,e){var f=[];b.bind("click",function(a){if(1===a.which){for(var b=[],d=[],e=0;e<f.length;e++)f[e]._clicked?f[e]._clicked=!1:f[e].$waiting||("cancel"===f[e]._blur&&b.push(f[e]),"submit"===f[e]._blur&&d.push(f[e]));(b.length||d.length)&&c.$apply(function(){angular.forEach(b,function(a){a.$cancel()}),angular.forEach(d,function(a){a.$submit()})})}});var g={$addEditable:function(a){this.$editables.push(a),a.elem.bind("$destroy",angular.bind(this,this.$removeEditable,a)),a.scope.$form||(a.scope.$form=this),this.$visible&&a.catchError(a.show())},$removeEditable:function(a){for(var b=0;b<this.$editables.length;b++)if(this.$editables[b]===a)return this.$editables.splice(b,1),void 0},$show:function(){if(!this.$visible){this.$visible=!0;var a=d();a.when(this.$onshow()),this.$setError(null,""),angular.forEach(this.$editables,function(b){a.when(b.show())}),a.then({onWait:angular.bind(this,this.$setWaiting),onTrue:angular.bind(this,this.$activate),onFalse:angular.bind(this,this.$activate),onString:angular.bind(this,this.$activate)}),setTimeout(angular.bind(this,function(){this._clicked=!1,-1===e.indexOf(f,this)&&f.push(this)}),0)}},$activate:function(a){var b;if(this.$editables.length){if(angular.isString(a))for(b=0;b<this.$editables.length;b++)if(this.$editables[b].name===a)return this.$editables[b].activate(),void 0;for(b=0;b<this.$editables.length;b++)if(this.$editables[b].error)return this.$editables[b].activate(),void 0;this.$editables[0].activate()}},$hide:function(){this.$visible&&(this.$visible=!1,this.$onhide(),angular.forEach(this.$editables,function(a){a.hide()}),e.arrayRemove(f,this))},$cancel:function(){this.$visible&&(this.$oncancel(),angular.forEach(this.$editables,function(a){a.cancel()}),this.$hide())},$setWaiting:function(a){this.$waiting=!!a,angular.forEach(this.$editables,function(b){b.setWaiting(!!a)})},$setError:function(a,b){angular.forEach(this.$editables,function(c){a&&c.name!==a||c.setError(b)})},$submit:function(){function a(a){var b=d();b.when(this.$onbeforesave()),b.then({onWait:angular.bind(this,this.$setWaiting),onTrue:a?angular.bind(this,this.$save):angular.bind(this,this.$hide),onFalse:angular.bind(this,this.$hide),onString:angular.bind(this,this.$activate)})}if(!this.$waiting){this.$setError(null,"");var b=d();angular.forEach(this.$editables,function(a){b.when(a.onbeforesave())}),b.then({onWait:angular.bind(this,this.$setWaiting),onTrue:angular.bind(this,a,!0),onFalse:angular.bind(this,a,!1),onString:angular.bind(this,this.$activate)})}},$save:function(){angular.forEach(this.$editables,function(a){a.save()});var a=d();a.when(this.$onaftersave()),angular.forEach(this.$editables,function(b){a.when(b.onaftersave())}),a.then({onWait:angular.bind(this,this.$setWaiting),onTrue:angular.bind(this,this.$hide),onFalse:angular.bind(this,this.$hide),onString:angular.bind(this,this.$activate)})},$onshow:angular.noop,$oncancel:angular.noop,$onhide:angular.noop,$onbeforesave:angular.noop,$onaftersave:angular.noop};return function(){return angular.extend({$editables:[],$visible:!1,$waiting:!1,$data:{},_clicked:!1,_blur:null},g)}}]),angular.module("xeditable").directive("editableForm",["$rootScope","$parse","editableFormController","editableOptions",function(a,b,c,d){return{restrict:"A",require:["form"],compile:function(){return{pre:function(b,d,e,f){var g,h=f[0];e.editableForm?b[e.editableForm]&&b[e.editableForm].$show?(g=b[e.editableForm],angular.extend(h,g)):(g=c(),b[e.editableForm]=g,angular.extend(g,h)):(g=c(),angular.extend(h,g));var i=a.$$editableBuffer,j=h.$name;j&&i&&i[j]&&(angular.forEach(i[j],function(a){g.$addEditable(a)}),delete i[j])},post:function(a,c,e,f){var g;g=e.editableForm&&a[e.editableForm]&&a[e.editableForm].$show?a[e.editableForm]:f[0],e.onshow&&(g.$onshow=angular.bind(g,b(e.onshow),a)),e.onhide&&(g.$onhide=angular.bind(g,b(e.onhide),a)),e.oncancel&&(g.$oncancel=angular.bind(g,b(e.oncancel),a)),e.shown&&b(e.shown)(a)&&g.$show(),g._blur=e.blur||d.blurForm,e.ngSubmit||e.submit||(e.onbeforesave&&(g.$onbeforesave=function(){return b(e.onbeforesave)(a,{$data:g.$data})}),e.onaftersave&&(g.$onaftersave=function(){return b(e.onaftersave)(a,{$data:g.$data})}),c.bind("submit",function(b){b.preventDefault(),a.$apply(function(){g.$submit()})})),c.bind("click",function(a){1===a.which&&g.$visible&&(g._clicked=!0)})}}}}}]),angular.module("xeditable").factory("editablePromiseCollection",["$q",function(a){function b(){return{promises:[],hasFalse:!1,hasString:!1,when:function(b,c){if(b===!1)this.hasFalse=!0;else if(!c&&angular.isObject(b))this.promises.push(a.when(b));else{if(!angular.isString(b))return;this.hasString=!0}},then:function(b){function c(){h.hasString||h.hasFalse?!h.hasString&&h.hasFalse?e():f():d()}b=b||{};var d=b.onTrue||angular.noop,e=b.onFalse||angular.noop,f=b.onString||angular.noop,g=b.onWait||angular.noop,h=this;this.promises.length?(g(!0),a.all(this.promises).then(function(a){g(!1),angular.forEach(a,function(a){h.when(a,!0)}),c()},function(){g(!1),f()})):c()}}}return b}]),angular.module("xeditable").factory("editableUtils",[function(){return{indexOf:function(a,b){if(a.indexOf)return a.indexOf(b);for(var c=0;c<a.length;c++)if(b===a[c])return c;return-1},arrayRemove:function(a,b){var c=this.indexOf(a,b);return c>=0&&a.splice(c,1),b},camelToDash:function(a){var b=/[A-Z]/g;return a.replace(b,function(a,b){return(b?"-":"")+a.toLowerCase()})},dashToCamel:function(a){var b=/([\:\-\_]+(.))/g,c=/^moz([A-Z])/;return a.replace(b,function(a,b,c,d){return d?c.toUpperCase():c}).replace(c,"Moz$1")}}}]),angular.module("xeditable").factory("editableNgOptionsParser",[function(){function a(a){var c;if(!(c=a.match(b)))throw"ng-options parse error";var d,e=c[2]||c[1],f=c[4]||c[6],g=c[5],h=(c[3]||"",c[2]?c[1]:f),i=c[7],j=c[8],k=j?c[8]:null;return void 0===g?(d=f+" in "+i,void 0!==j&&(d+=" track by "+k)):d="("+g+", "+f+") in "+i,{ngRepeat:d,locals:{valueName:f,keyName:g,valueFn:h,displayFn:e}}}var b=/^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/;return a}]),angular.module("xeditable").factory("editableThemes",function(){var a={"default":{formTpl:'<form class="editable-wrap"></form>',noformTpl:'<span class="editable-wrap"></span>',controlsTpl:'<span class="editable-controls"></span>',inputTpl:"",errorTpl:'<div class="editable-error" ng-show="$error" ng-bind="$error"></div>',buttonsTpl:'<span class="editable-buttons"></span>',submitTpl:'<button type="submit">save</button>',cancelTpl:'<button type="button" ng-click="$form.$cancel()">cancel</button>'},bs2:{formTpl:'<form class="form-inline editable-wrap" role="form"></form>',noformTpl:'<span class="editable-wrap"></span>',controlsTpl:'<div class="editable-controls controls control-group" ng-class="{\'error\': $error}"></div>',inputTpl:"",errorTpl:'<div class="editable-error help-block" ng-show="$error" ng-bind="$error"></div>',buttonsTpl:'<span class="editable-buttons"></span>',submitTpl:'<button type="submit" class="btn btn-primary"><span class="icon-ok icon-white"></span></button>',cancelTpl:'<button type="button" class="btn" ng-click="$form.$cancel()"><span class="icon-remove"></span></button>'},bs3:{formTpl:'<form class="form-inline editable-wrap" role="form"></form>',noformTpl:'<span class="editable-wrap"></span>',controlsTpl:'<div class="editable-controls form-group" ng-class="{\'has-error\': $error}"></div>',inputTpl:"",errorTpl:'<div class="editable-error help-block" ng-show="$error" ng-bind="$error"></div>',buttonsTpl:'<span class="editable-buttons"></span>',submitTpl:'<button type="submit" class="btn btn-primary"><span class="glyphicon glyphicon-ok"></span></button>',cancelTpl:'<button type="button" class="btn btn-default" ng-click="$form.$cancel()"><span class="glyphicon glyphicon-remove"></span></button>',buttonsClass:"",inputClass:"",postrender:function(){switch(this.directiveName){case"editableText":case"editableSelect":case"editableTextarea":case"editableEmail":case"editableTel":case"editableNumber":case"editableUrl":case"editableSearch":case"editableDate":case"editableDatetime":case"editableTime":case"editableMonth":case"editableWeek":if(this.inputEl.addClass("form-control"),this.theme.inputClass){if(this.inputEl.attr("multiple")&&("input-sm"===this.theme.inputClass||"input-lg"===this.theme.inputClass))break;this.inputEl.addClass(this.theme.inputClass)}}this.buttonsEl&&this.theme.buttonsClass&&this.buttonsEl.find("button").addClass(this.theme.buttonsClass)}}};return a}); angular.module("xeditable", []).value("editableOptions", {
\ No newline at end of file theme: "default",
buttons: "right",
blurElem: "cancel",
blurForm: "ignore",
activate: "focus"
}), angular.module("xeditable").directive("editableBsdate", ["editableDirectiveFactory", function (a) {
return a({directiveName: "editableBsdate", inputTpl: '<input type="text">'})
}]), angular.module("xeditable").directive("editableBstime", ["editableDirectiveFactory", function (a) {
return a({
directiveName: "editableBstime", inputTpl: "<timepicker></timepicker>", render: function () {
this.parent.render.call(this);
var a = angular.element('<div class="well well-small" style="display:inline-block;"></div>');
a.attr("ng-model", this.inputEl.attr("ng-model")), this.inputEl.removeAttr("ng-model"), this.attrs.eNgChange && (a.attr("ng-change", this.inputEl.attr("ng-change")), this.inputEl.removeAttr("ng-change")), this.inputEl.wrap(a)
}
})
}]), angular.module("xeditable").directive("editableCheckbox", ["editableDirectiveFactory", function (a) {
return a({
directiveName: "editableCheckbox", inputTpl: '<input type="checkbox">', render: function () {
this.parent.render.call(this), this.attrs.eTitle && (this.inputEl.wrap("<label></label>"), this.inputEl.after(angular.element("<span></span>").text(this.attrs.eTitle)))
}, autosubmit: function () {
var a = this;
a.inputEl.bind("change", function () {
setTimeout(function () {
a.scope.$apply(function () {
a.scope.$form.$submit()
})
}, 500)
})
}
})
}]), angular.module("xeditable").directive("editableChecklist", ["editableDirectiveFactory", "editableNgOptionsParser", function (a, b) {
return a({
directiveName: "editableChecklist", inputTpl: "<span></span>", useCopy: !0, render: function () {
this.parent.render.call(this);
var a = b(this.attrs.eNgOptions), c = '<label ng-repeat="' + a.ngRepeat + '">' + '<input type="checkbox" checklist-model="$parent.$data" checklist-value="' + a.locals.valueFn + '">' + '<span ng-bind="' + a.locals.displayFn + '"></span></label>';
this.inputEl.removeAttr("ng-model"), this.inputEl.removeAttr("ng-options"), this.inputEl.html(c)
}
})
}]), function () {
var a = "text|email|tel|number|url|search|color|date|datetime|time|month|week".split("|");
angular.forEach(a, function (a) {
var b = "editable" + a.charAt(0).toUpperCase() + a.slice(1);
angular.module("xeditable").directive(b, ["editableDirectiveFactory", function (c) {
return c({directiveName: b, inputTpl: '<input type="' + a + '">'})
}])
}), angular.module("xeditable").directive("editableRange", ["editableDirectiveFactory", function (a) {
return a({
directiveName: "editableRange",
inputTpl: '<input type="range" id="range" name="range">',
render: function () {
this.parent.render.call(this), this.inputEl.after("<output>{{$data}}</output>")
}
})
}])
}(), angular.module("xeditable").directive("editableRadiolist", ["editableDirectiveFactory", "editableNgOptionsParser", function (a, b) {
return a({
directiveName: "editableRadiolist", inputTpl: "<span></span>", render: function () {
this.parent.render.call(this);
var a = b(this.attrs.eNgOptions), c = '<label ng-repeat="' + a.ngRepeat + '">' + '<input type="radio" ng-model="$parent.$data" value="{{' + a.locals.valueFn + '}}">' + '<span ng-bind="' + a.locals.displayFn + '"></span></label>';
this.inputEl.removeAttr("ng-model"), this.inputEl.removeAttr("ng-options"), this.inputEl.html(c)
}, autosubmit: function () {
var a = this;
a.inputEl.bind("change", function () {
setTimeout(function () {
a.scope.$apply(function () {
a.scope.$form.$submit()
})
}, 500)
})
}
})
}]), angular.module("xeditable").directive("editableSelect", ["editableDirectiveFactory", function (a) {
return a({
directiveName: "editableSelect", inputTpl: "<select></select>", autosubmit: function () {
var a = this;
a.inputEl.bind("change", function () {
a.scope.$apply(function () {
a.scope.$form.$submit()
})
})
}
})
}]), angular.module("xeditable").directive("editableTextarea", ["editableDirectiveFactory", function (a) {
return a({
directiveName: "editableTextarea", inputTpl: "<textarea></textarea>", addListeners: function () {
var a = this;
a.parent.addListeners.call(a), a.single && "no" !== a.buttons && a.autosubmit()
}, autosubmit: function () {
var a = this;
a.inputEl.bind("keydown", function (b) {
(b.ctrlKey || b.metaKey) && 13 === b.keyCode && a.scope.$apply(function () {
a.scope.$form.$submit()
})
})
}
})
}]), angular.module("xeditable").factory("editableController", ["$q", "editableUtils", function (a, b) {
function c(a, c, d, e, f, g, h, i, j) {
var k, l, m = this;
m.scope = a, m.elem = d, m.attrs = c, m.inputEl = null, m.editorEl = null, m.single = !0, m.error = "", m.theme = f[g.theme] || f["default"], m.parent = {}, m.inputTpl = "", m.directiveName = "", m.useCopy = !1, m.single = null, m.buttons = "right", m.init = function (b) {
if (m.single = b, m.name = c.eName || c[m.directiveName], !c[m.directiveName])throw"You should provide value for `" + m.directiveName + "` in editable element!";
k = e(c[m.directiveName]), m.buttons = m.single ? m.attrs.buttons || g.buttons : "no", c.eName && m.scope.$watch("$data", function (a) {
m.scope.$form.$data[c.eName] = a
}), c.onshow && (m.onshow = function () {
return m.catchError(e(c.onshow)(a))
}), c.onhide && (m.onhide = function () {
return e(c.onhide)(a)
}), c.oncancel && (m.oncancel = function () {
return e(c.oncancel)(a)
}), c.onbeforesave && (m.onbeforesave = function () {
return m.catchError(e(c.onbeforesave)(a))
}), c.onaftersave && (m.onaftersave = function () {
return m.catchError(e(c.onaftersave)(a))
}), a.$parent.$watch(c[m.directiveName], function () {
m.handleEmpty()
})
}, m.render = function () {
var a = m.theme;
m.inputEl = angular.element(m.inputTpl), m.controlsEl = angular.element(a.controlsTpl), m.controlsEl.append(m.inputEl), "no" !== m.buttons && (m.buttonsEl = angular.element(a.buttonsTpl), m.submitEl = angular.element(a.submitTpl), m.cancelEl = angular.element(a.cancelTpl), m.buttonsEl.append(m.submitEl).append(m.cancelEl), m.controlsEl.append(m.buttonsEl), m.inputEl.addClass("editable-has-buttons")), m.errorEl = angular.element(a.errorTpl), m.controlsEl.append(m.errorEl), m.editorEl = angular.element(m.single ? a.formTpl : a.noformTpl), m.editorEl.append(m.controlsEl);
for (var d in c.$attr)if (!(d.length <= 1)) {
var e = !1, f = d.substring(1, 2);
if ("e" === d.substring(0, 1) && f === f.toUpperCase() && (e = d.substring(1), "Form" !== e && "NgSubmit" !== e)) {
e = e.substring(0, 1).toLowerCase() + b.camelToDash(e.substring(1));
var h = "" === c[d] ? e : c[d];
m.inputEl.attr(e, h)
}
}
m.inputEl.addClass("editable-input"), m.inputEl.attr("ng-model", "$data"), m.editorEl.addClass(b.camelToDash(m.directiveName)), m.single && (m.editorEl.attr("editable-form", "$form"), m.editorEl.attr("blur", m.attrs.blur || ("no" === m.buttons ? "cancel" : g.blurElem))), angular.isFunction(a.postrender) && a.postrender.call(m)
}, m.setLocalValue = function () {
m.scope.$data = m.useCopy ? angular.copy(k(a.$parent)) : k(a.$parent)
}, m.show = function () {
return m.setLocalValue(), m.render(), d.after(m.editorEl), i(m.editorEl)(a), m.addListeners(), d.addClass("editable-hide"), m.onshow()
}, m.hide = function () {
return m.editorEl.remove(), d.removeClass("editable-hide"), m.onhide()
}, m.cancel = function () {
m.oncancel()
}, m.addListeners = function () {
m.inputEl.bind("keyup", function (a) {
if (m.single)switch (a.keyCode) {
case 27:
m.scope.$apply(function () {
m.scope.$form.$cancel()
})
}
}), m.single && "no" === m.buttons && m.autosubmit(), m.editorEl.bind("click", function (a) {
1 === a.which && m.scope.$form.$visible && (m.scope.$form._clicked = !0)
})
}, m.setWaiting = function (a) {
a ? (l = !m.inputEl.attr("disabled") && !m.inputEl.attr("ng-disabled") && !m.inputEl.attr("ng-enabled"), l && (m.inputEl.attr("disabled", "disabled"), m.buttonsEl && m.buttonsEl.find("button").attr("disabled", "disabled"))) : l && (m.inputEl.removeAttr("disabled"), m.buttonsEl && m.buttonsEl.find("button").removeAttr("disabled"))
}, m.activate = function () {
setTimeout(function () {
var a = m.inputEl[0];
"focus" === g.activate && a.focus && a.focus(), "select" === g.activate && a.select && a.select()
}, 0)
}, m.setError = function (b) {
angular.isObject(b) || (a.$error = b, m.error = b)
}, m.catchError = function (a, b) {
return angular.isObject(a) && b !== !0 ? j.when(a).then(angular.bind(this, function (a) {
this.catchError(a, !0)
}), angular.bind(this, function (a) {
this.catchError(a, !0)
})) : b && angular.isObject(a) && a.status && 200 !== a.status && a.data && angular.isString(a.data) ? (this.setError(a.data), a = a.data) : angular.isString(a) && this.setError(a), a
}, m.save = function () {
k.assign(a.$parent, angular.copy(m.scope.$data))
}, m.handleEmpty = function () {
var b = k(a.$parent), c = null === b || void 0 === b || "" === b || angular.isArray(b) && 0 === b.length;
d.toggleClass("editable-empty", c)
}, m.autosubmit = angular.noop, m.onshow = angular.noop, m.onhide = angular.noop, m.oncancel = angular.noop, m.onbeforesave = angular.noop, m.onaftersave = angular.noop
}
return c.$inject = ["$scope", "$attrs", "$element", "$parse", "editableThemes", "editableOptions", "$rootScope", "$compile", "$q"], c
}]), angular.module("xeditable").factory("editableDirectiveFactory", ["$parse", "$compile", "editableThemes", "$rootScope", "$document", "editableController", "editableFormController", function (a, b, c, d, e, f, g) {
return function (b) {
return {
restrict: "A",
scope: !0,
require: [b.directiveName, "?^form"],
controller: f,
link: function (c, f, h, i) {
var j, k = i[0], l = !1;
if (i[1])j = i[1], l = !0; else if (h.eForm) {
var m = a(h.eForm)(c);
if (m)j = m, l = !0; else for (var n = 0; n < e[0].forms.length; n++)if (e[0].forms[n].name === h.eForm) {
j = null, l = !0;
break
}
}
if (angular.forEach(b, function (a, b) {
void 0 !== k[b] && (k.parent[b] = k[b])
}), angular.extend(k, b), k.init(!l), c.$editable = k, f.addClass("editable"), l)if (j) {
if (c.$form = j, !c.$form.$addEditable)throw"Form with editable elements should have `editable-form` attribute.";
c.$form.$addEditable(k)
} else d.$$editableBuffer = d.$$editableBuffer || {}, d.$$editableBuffer[h.eForm] = d.$$editableBuffer[h.eForm] || [], d.$$editableBuffer[h.eForm].push(k), c.$form = null; else c.$form = g(), c.$form.$addEditable(k), h.eForm && (c.$parent[h.eForm] = c.$form), h.eForm || (f.addClass("editable-click"), f.bind("click", function (a) {
a.preventDefault(), a.editable = k, c.$apply(function () {
c.$form.$show()
})
}))
}
}
}
}]), angular.module("xeditable").factory("editableFormController", ["$parse", "$document", "$rootScope", "editablePromiseCollection", "editableUtils", function (a, b, c, d, e) {
var f = [];
b.bind("click", function (a) {
if (1 === a.which) {
for (var b = [], d = [], e = 0; e < f.length; e++)f[e]._clicked ? f[e]._clicked = !1 : f[e].$waiting || ("cancel" === f[e]._blur && b.push(f[e]), "submit" === f[e]._blur && d.push(f[e]));
(b.length || d.length) && c.$apply(function () {
angular.forEach(b, function (a) {
a.$cancel()
}), angular.forEach(d, function (a) {
a.$submit()
})
})
}
});
var g = {
$addEditable: function (a) {
this.$editables.push(a), a.elem.bind("$destroy", angular.bind(this, this.$removeEditable, a)), a.scope.$form || (a.scope.$form = this), this.$visible && a.catchError(a.show())
},
$removeEditable: function (a) {
for (var b = 0; b < this.$editables.length; b++)if (this.$editables[b] === a)return this.$editables.splice(b, 1), void 0
},
$show: function () {
if (!this.$visible) {
this.$visible = !0;
var a = d();
a.when(this.$onshow()), this.$setError(null, ""), angular.forEach(this.$editables, function (b) {
a.when(b.show())
}), a.then({
onWait: angular.bind(this, this.$setWaiting),
onTrue: angular.bind(this, this.$activate),
onFalse: angular.bind(this, this.$activate),
onString: angular.bind(this, this.$activate)
}), setTimeout(angular.bind(this, function () {
this._clicked = !1, -1 === e.indexOf(f, this) && f.push(this)
}), 0)
}
},
$activate: function (a) {
var b;
if (this.$editables.length) {
if (angular.isString(a))for (b = 0; b < this.$editables.length; b++)if (this.$editables[b].name === a)return this.$editables[b].activate(), void 0;
for (b = 0; b < this.$editables.length; b++)if (this.$editables[b].error)return this.$editables[b].activate(), void 0;
this.$editables[0].activate()
}
},
$hide: function () {
this.$visible && (this.$visible = !1, this.$onhide(), angular.forEach(this.$editables, function (a) {
a.hide()
}), e.arrayRemove(f, this))
},
$cancel: function () {
this.$visible && (this.$oncancel(), angular.forEach(this.$editables, function (a) {
a.cancel()
}), this.$hide())
},
$setWaiting: function (a) {
this.$waiting = !!a, angular.forEach(this.$editables, function (b) {
b.setWaiting(!!a)
})
},
$setError: function (a, b) {
angular.forEach(this.$editables, function (c) {
a && c.name !== a || c.setError(b)
})
},
$submit: function () {
function a(a) {
var b = d();
b.when(this.$onbeforesave()), b.then({
onWait: angular.bind(this, this.$setWaiting),
onTrue: a ? angular.bind(this, this.$save) : angular.bind(this, this.$hide),
onFalse: angular.bind(this, this.$hide),
onString: angular.bind(this, this.$activate)
})
}
if (!this.$waiting) {
this.$setError(null, "");
var b = d();
angular.forEach(this.$editables, function (a) {
b.when(a.onbeforesave())
}), b.then({
onWait: angular.bind(this, this.$setWaiting),
onTrue: angular.bind(this, a, !0),
onFalse: angular.bind(this, a, !1),
onString: angular.bind(this, this.$activate)
})
}
},
$save: function () {
angular.forEach(this.$editables, function (a) {
a.save()
});
var a = d();
a.when(this.$onaftersave()), angular.forEach(this.$editables, function (b) {
a.when(b.onaftersave())
}), a.then({
onWait: angular.bind(this, this.$setWaiting),
onTrue: angular.bind(this, this.$hide),
onFalse: angular.bind(this, this.$hide),
onString: angular.bind(this, this.$activate)
})
},
$onshow: angular.noop,
$oncancel: angular.noop,
$onhide: angular.noop,
$onbeforesave: angular.noop,
$onaftersave: angular.noop
};
return function () {
return angular.extend({$editables: [], $visible: !1, $waiting: !1, $data: {}, _clicked: !1, _blur: null}, g)
}
}]), angular.module("xeditable").directive("editableForm", ["$rootScope", "$parse", "editableFormController", "editableOptions", function (a, b, c, d) {
return {
restrict: "A", require: ["form"], compile: function () {
return {
pre: function (b, d, e, f) {
var g, h = f[0];
e.editableForm ? b[e.editableForm] && b[e.editableForm].$show ? (g = b[e.editableForm], angular.extend(h, g)) : (g = c(), b[e.editableForm] = g, angular.extend(g, h)) : (g = c(), angular.extend(h, g));
var i = a.$$editableBuffer, j = h.$name;
j && i && i[j] && (angular.forEach(i[j], function (a) {
g.$addEditable(a)
}), delete i[j])
}, post: function (a, c, e, f) {
var g;
g = e.editableForm && a[e.editableForm] && a[e.editableForm].$show ? a[e.editableForm] : f[0], e.onshow && (g.$onshow = angular.bind(g, b(e.onshow), a)), e.onhide && (g.$onhide = angular.bind(g, b(e.onhide), a)), e.oncancel && (g.$oncancel = angular.bind(g, b(e.oncancel), a)), e.shown && b(e.shown)(a) && g.$show(), g._blur = e.blur || d.blurForm, e.ngSubmit || e.submit || (e.onbeforesave && (g.$onbeforesave = function () {
return b(e.onbeforesave)(a, {$data: g.$data})
}), e.onaftersave && (g.$onaftersave = function () {
return b(e.onaftersave)(a, {$data: g.$data})
}), c.bind("submit", function (b) {
b.preventDefault(), a.$apply(function () {
g.$submit()
})
})), c.bind("click", function (a) {
1 === a.which && g.$visible && (g._clicked = !0)
})
}
}
}
}
}]), angular.module("xeditable").factory("editablePromiseCollection", ["$q", function (a) {
function b() {
return {
promises: [], hasFalse: !1, hasString: !1, when: function (b, c) {
if (b === !1)this.hasFalse = !0; else if (!c && angular.isObject(b))this.promises.push(a.when(b)); else {
if (!angular.isString(b))return;
this.hasString = !0
}
}, then: function (b) {
function c() {
h.hasString || h.hasFalse ? !h.hasString && h.hasFalse ? e() : f() : d()
}
b = b || {};
var d = b.onTrue || angular.noop, e = b.onFalse || angular.noop, f = b.onString || angular.noop, g = b.onWait || angular.noop, h = this;
this.promises.length ? (g(!0), a.all(this.promises).then(function (a) {
g(!1), angular.forEach(a, function (a) {
h.when(a, !0)
}), c()
}, function () {
g(!1), f()
})) : c()
}
}
}
return b
}]), angular.module("xeditable").factory("editableUtils", [function () {
return {
indexOf: function (a, b) {
if (a.indexOf)return a.indexOf(b);
for (var c = 0; c < a.length; c++)if (b === a[c])return c;
return -1
}, arrayRemove: function (a, b) {
var c = this.indexOf(a, b);
return c >= 0 && a.splice(c, 1), b
}, camelToDash: function (a) {
var b = /[A-Z]/g;
return a.replace(b, function (a, b) {
return (b ? "-" : "") + a.toLowerCase()
})
}, dashToCamel: function (a) {
var b = /([\:\-\_]+(.))/g, c = /^moz([A-Z])/;
return a.replace(b, function (a, b, c, d) {
return d ? c.toUpperCase() : c
}).replace(c, "Moz$1")
}
}
}]), angular.module("xeditable").factory("editableNgOptionsParser", [function () {
function a(a) {
var c;
if (!(c = a.match(b)))throw"ng-options parse error";
var d, e = c[2] || c[1], f = c[4] || c[6], g = c[5], h = (c[3] || "", c[2] ? c[1] : f), i = c[7], j = c[8], k = j ? c[8] : null;
return void 0 === g ? (d = f + " in " + i, void 0 !== j && (d += " track by " + k)) : d = "(" + g + ", " + f + ") in " + i, {
ngRepeat: d,
locals: {valueName: f, keyName: g, valueFn: h, displayFn: e}
}
}
var b = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/;
return a
}]), angular.module("xeditable").factory("editableThemes", function () {
var a = {
"default": {
formTpl: '<form class="editable-wrap"></form>',
noformTpl: '<span class="editable-wrap"></span>',
controlsTpl: '<span class="editable-controls"></span>',
inputTpl: "",
errorTpl: '<div class="editable-error" ng-show="$error" ng-bind="$error"></div>',
buttonsTpl: '<span class="editable-buttons"></span>',
submitTpl: '<button type="submit">save</button>',
cancelTpl: '<button type="button" ng-click="$form.$cancel()">cancel</button>'
},
bs2: {
formTpl: '<form class="form-inline editable-wrap" role="form"></form>',
noformTpl: '<span class="editable-wrap"></span>',
controlsTpl: '<div class="editable-controls controls control-group" ng-class="{\'error\': $error}"></div>',
inputTpl: "",
errorTpl: '<div class="editable-error help-block" ng-show="$error" ng-bind="$error"></div>',
buttonsTpl: '<span class="editable-buttons"></span>',
submitTpl: '<button type="submit" class="btn btn-primary"><span class="icon-ok icon-white"></span></button>',
cancelTpl: '<button type="button" class="btn" ng-click="$form.$cancel()"><span class="icon-remove"></span></button>'
},
bs3: {
formTpl: '<form class="form-inline editable-wrap" role="form"></form>',
noformTpl: '<span class="editable-wrap"></span>',
controlsTpl: '<div class="editable-controls form-group" ng-class="{\'has-error\': $error}"></div>',
inputTpl: "",
errorTpl: '<div class="editable-error help-block" ng-show="$error" ng-bind="$error"></div>',
buttonsTpl: '<span class="editable-buttons"></span>',
submitTpl: '<button type="submit" class="btn btn-primary"><span class="glyphicon glyphicon-ok"></span></button>',
cancelTpl: '<button type="button" class="btn btn-default" ng-click="$form.$cancel()"><span class="glyphicon glyphicon-remove"></span></button>',
buttonsClass: "",
inputClass: "",
postrender: function () {
switch (this.directiveName) {
case"editableText":
case"editableSelect":
case"editableTextarea":
case"editableEmail":
case"editableTel":
case"editableNumber":
case"editableUrl":
case"editableSearch":
case"editableDate":
case"editableDatetime":
case"editableTime":
case"editableMonth":
case"editableWeek":
if (this.inputEl.addClass("form-control"), this.theme.inputClass) {
if (this.inputEl.attr("multiple") && ("input-sm" === this.theme.inputClass || "input-lg" === this.theme.inputClass))break;
this.inputEl.addClass(this.theme.inputClass)
}
}
this.buttonsEl && this.theme.buttonsClass && this.buttonsEl.find("button").addClass(this.theme.buttonsClass)
}
}
};
return a
});
...@@ -11,4 +11,478 @@ ...@@ -11,4 +11,478 @@
* Bootstrap v3.3.5 (http://getbootstrap.com) * Bootstrap v3.3.5 (http://getbootstrap.com)
* Copyright 2011-2015 Twitter, Inc. * Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/.btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-default.disabled,.btn-primary.disabled,.btn-success.disabled,.btn-info.disabled,.btn-warning.disabled,.btn-danger.disabled,.btn-default[disabled],.btn-primary[disabled],.btn-success[disabled],.btn-info[disabled],.btn-warning[disabled],.btn-danger[disabled],fieldset[disabled] .btn-default,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-info,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-danger{-webkit-box-shadow:none;box-shadow:none}.btn-default .badge,.btn-primary .badge,.btn-success .badge,.btn-info .badge,.btn-warning .badge,.btn-danger .badge{text-shadow:none}.btn:active,.btn.active{background-image:none}.btn-default{background-image:-webkit-linear-gradient(top, #fff 0, #e0e0e0 100%);background-image:-o-linear-gradient(top, #fff 0, #e0e0e0 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #fff), to(#e0e0e0));background-image:linear-gradient(to bottom, #fff 0, #e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background-repeat:repeat-x;border-color:#dbdbdb;text-shadow:0 1px 0 #fff;border-color:#ccc}.btn-default:hover,.btn-default:focus{background-color:#e0e0e0;background-position:0 -15px}.btn-default:active,.btn-default.active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top, #337ab7 0, #265a88 100%);background-image:-o-linear-gradient(top, #337ab7 0, #265a88 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #337ab7), to(#265a88));background-image:linear-gradient(to bottom, #337ab7 0, #265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background-repeat:repeat-x;border-color:#245580}.btn-primary:hover,.btn-primary:focus{background-color:#265a88;background-position:0 -15px}.btn-primary:active,.btn-primary.active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top, #5cb85c 0, #419641 100%);background-image:-o-linear-gradient(top, #5cb85c 0, #419641 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #5cb85c), to(#419641));background-image:linear-gradient(to bottom, #5cb85c 0, #419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:hover,.btn-success:focus{background-color:#419641;background-position:0 -15px}.btn-success:active,.btn-success.active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top, #5bc0de 0, #2aabd2 100%);background-image:-o-linear-gradient(top, #5bc0de 0, #2aabd2 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #5bc0de), to(#2aabd2));background-image:linear-gradient(to bottom, #5bc0de 0, #2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:hover,.btn-info:focus{background-color:#2aabd2;background-position:0 -15px}.btn-info:active,.btn-info.active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top, #f0ad4e 0, #eb9316 100%);background-image:-o-linear-gradient(top, #f0ad4e 0, #eb9316 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #f0ad4e), to(#eb9316));background-image:linear-gradient(to bottom, #f0ad4e 0, #eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:hover,.btn-warning:focus{background-color:#eb9316;background-position:0 -15px}.btn-warning:active,.btn-warning.active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top, #d9534f 0, #c12e2a 100%);background-image:-o-linear-gradient(top, #d9534f 0, #c12e2a 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #d9534f), to(#c12e2a));background-image:linear-gradient(to bottom, #d9534f 0, #c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:hover,.btn-danger:focus{background-color:#c12e2a;background-position:0 -15px}.btn-danger:active,.btn-danger.active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#c12e2a;background-image:none}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-image:-webkit-linear-gradient(top, #f5f5f5 0, #e8e8e8 100%);background-image:-o-linear-gradient(top, #f5f5f5 0, #e8e8e8 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #f5f5f5), to(#e8e8e8));background-image:linear-gradient(to bottom, #f5f5f5 0, #e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-color:#e8e8e8}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-image:-webkit-linear-gradient(top, #337ab7 0, #2e6da4 100%);background-image:-o-linear-gradient(top, #337ab7 0, #2e6da4 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #337ab7), to(#2e6da4));background-image:linear-gradient(to bottom, #337ab7 0, #2e6da4 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-color:#2e6da4}.navbar-default{background-image:-webkit-linear-gradient(top, #fff 0, #f8f8f8 100%);background-image:-o-linear-gradient(top, #fff 0, #f8f8f8 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #fff), to(#f8f8f8));background-image:linear-gradient(to bottom, #fff 0, #f8f8f8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075)}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top, #dbdbdb 0, #e2e2e2 100%);background-image:-o-linear-gradient(top, #dbdbdb 0, #e2e2e2 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #dbdbdb), to(#e2e2e2));background-image:linear-gradient(to bottom, #dbdbdb 0, #e2e2e2 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,0.075);box-shadow:inset 0 3px 9px rgba(0,0,0,0.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,0.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top, #3c3c3c 0, #222 100%);background-image:-o-linear-gradient(top, #3c3c3c 0, #222 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #3c3c3c), to(#222));background-image:linear-gradient(to bottom, #3c3c3c 0, #222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);border-radius:4px}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top, #080808 0, #0f0f0f 100%);background-image:-o-linear-gradient(top, #080808 0, #0f0f0f 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #080808), to(#0f0f0f));background-image:linear-gradient(to bottom, #080808 0, #0f0f0f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,0.25);box-shadow:inset 0 3px 9px rgba(0,0,0,0.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-image:-webkit-linear-gradient(top, #337ab7 0, #2e6da4 100%);background-image:-o-linear-gradient(top, #337ab7 0, #2e6da4 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #337ab7), to(#2e6da4));background-image:linear-gradient(to bottom, #337ab7 0, #2e6da4 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0)}}.alert{text-shadow:0 1px 0 rgba(255,255,255,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05)}.alert-success{background-image:-webkit-linear-gradient(top, #dff0d8 0, #c8e5bc 100%);background-image:-o-linear-gradient(top, #dff0d8 0, #c8e5bc 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #dff0d8), to(#c8e5bc));background-image:linear-gradient(to bottom, #dff0d8 0, #c8e5bc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top, #d9edf7 0, #b9def0 100%);background-image:-o-linear-gradient(top, #d9edf7 0, #b9def0 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #d9edf7), to(#b9def0));background-image:linear-gradient(to bottom, #d9edf7 0, #b9def0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top, #fcf8e3 0, #f8efc0 100%);background-image:-o-linear-gradient(top, #fcf8e3 0, #f8efc0 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #fcf8e3), to(#f8efc0));background-image:linear-gradient(to bottom, #fcf8e3 0, #f8efc0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top, #f2dede 0, #e7c3c3 100%);background-image:-o-linear-gradient(top, #f2dede 0, #e7c3c3 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #f2dede), to(#e7c3c3));background-image:linear-gradient(to bottom, #f2dede 0, #e7c3c3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top, #ebebeb 0, #f5f5f5 100%);background-image:-o-linear-gradient(top, #ebebeb 0, #f5f5f5 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #ebebeb), to(#f5f5f5));background-image:linear-gradient(to bottom, #ebebeb 0, #f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0)}.progress-bar{background-image:-webkit-linear-gradient(top, #337ab7 0, #286090 100%);background-image:-o-linear-gradient(top, #337ab7 0, #286090 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #337ab7), to(#286090));background-image:linear-gradient(to bottom, #337ab7 0, #286090 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0)}.progress-bar-success{background-image:-webkit-linear-gradient(top, #5cb85c 0, #449d44 100%);background-image:-o-linear-gradient(top, #5cb85c 0, #449d44 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #5cb85c), to(#449d44));background-image:linear-gradient(to bottom, #5cb85c 0, #449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0)}.progress-bar-info{background-image:-webkit-linear-gradient(top, #5bc0de 0, #31b0d5 100%);background-image:-o-linear-gradient(top, #5bc0de 0, #31b0d5 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #5bc0de), to(#31b0d5));background-image:linear-gradient(to bottom, #5bc0de 0, #31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0)}.progress-bar-warning{background-image:-webkit-linear-gradient(top, #f0ad4e 0, #ec971f 100%);background-image:-o-linear-gradient(top, #f0ad4e 0, #ec971f 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #f0ad4e), to(#ec971f));background-image:linear-gradient(to bottom, #f0ad4e 0, #ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0)}.progress-bar-danger{background-image:-webkit-linear-gradient(top, #d9534f 0, #c9302c 100%);background-image:-o-linear-gradient(top, #d9534f 0, #c9302c 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #d9534f), to(#c9302c));background-image:linear-gradient(to bottom, #d9534f 0, #c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0)}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top, #337ab7 0, #2b669a 100%);background-image:-o-linear-gradient(top, #337ab7 0, #2b669a 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #337ab7), to(#2b669a));background-image:linear-gradient(to bottom, #337ab7 0, #2b669a 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:hover .badge,.list-group-item.active:focus .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top, #f5f5f5 0, #e8e8e8 100%);background-image:-o-linear-gradient(top, #f5f5f5 0, #e8e8e8 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #f5f5f5), to(#e8e8e8));background-image:linear-gradient(to bottom, #f5f5f5 0, #e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0)}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top, #337ab7 0, #2e6da4 100%);background-image:-o-linear-gradient(top, #337ab7 0, #2e6da4 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #337ab7), to(#2e6da4));background-image:linear-gradient(to bottom, #337ab7 0, #2e6da4 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0)}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top, #dff0d8 0, #d0e9c6 100%);background-image:-o-linear-gradient(top, #dff0d8 0, #d0e9c6 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #dff0d8), to(#d0e9c6));background-image:linear-gradient(to bottom, #dff0d8 0, #d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0)}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top, #d9edf7 0, #c4e3f3 100%);background-image:-o-linear-gradient(top, #d9edf7 0, #c4e3f3 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #d9edf7), to(#c4e3f3));background-image:linear-gradient(to bottom, #d9edf7 0, #c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0)}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top, #fcf8e3 0, #faf2cc 100%);background-image:-o-linear-gradient(top, #fcf8e3 0, #faf2cc 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #fcf8e3), to(#faf2cc));background-image:linear-gradient(to bottom, #fcf8e3 0, #faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0)}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top, #f2dede 0, #ebcccc 100%);background-image:-o-linear-gradient(top, #f2dede 0, #ebcccc 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #f2dede), to(#ebcccc));background-image:linear-gradient(to bottom, #f2dede 0, #ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0)}.well{background-image:-webkit-linear-gradient(top, #e8e8e8 0, #f5f5f5 100%);background-image:-o-linear-gradient(top, #e8e8e8 0, #f5f5f5 100%);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #e8e8e8), to(#f5f5f5));background-image:linear-gradient(to bottom, #e8e8e8 0, #f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1)} */
\ No newline at end of file .btn-default, .btn-primary, .btn-success, .btn-info, .btn-warning, .btn-danger {
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075)
}
.btn-default:active, .btn-primary:active, .btn-success:active, .btn-info:active, .btn-warning:active, .btn-danger:active, .btn-default.active, .btn-primary.active, .btn-success.active, .btn-info.active, .btn-warning.active, .btn-danger.active {
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125)
}
.btn-default.disabled, .btn-primary.disabled, .btn-success.disabled, .btn-info.disabled, .btn-warning.disabled, .btn-danger.disabled, .btn-default[disabled], .btn-primary[disabled], .btn-success[disabled], .btn-info[disabled], .btn-warning[disabled], .btn-danger[disabled], fieldset[disabled] .btn-default, fieldset[disabled] .btn-primary, fieldset[disabled] .btn-success, fieldset[disabled] .btn-info, fieldset[disabled] .btn-warning, fieldset[disabled] .btn-danger {
-webkit-box-shadow: none;
box-shadow: none
}
.btn-default .badge, .btn-primary .badge, .btn-success .badge, .btn-info .badge, .btn-warning .badge, .btn-danger .badge {
text-shadow: none
}
.btn:active, .btn.active {
background-image: none
}
.btn-default {
background-image: -webkit-linear-gradient(top, #fff 0, #e0e0e0 100%);
background-image: -o-linear-gradient(top, #fff 0, #e0e0e0 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #fff), to(#e0e0e0));
background-image: linear-gradient(to bottom, #fff 0, #e0e0e0 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
background-repeat: repeat-x;
border-color: #dbdbdb;
text-shadow: 0 1px 0 #fff;
border-color: #ccc
}
.btn-default:hover, .btn-default:focus {
background-color: #e0e0e0;
background-position: 0 -15px
}
.btn-default:active, .btn-default.active {
background-color: #e0e0e0;
border-color: #dbdbdb
}
.btn-default.disabled, .btn-default[disabled], fieldset[disabled] .btn-default, .btn-default.disabled:hover, .btn-default[disabled]:hover, fieldset[disabled] .btn-default:hover, .btn-default.disabled:focus, .btn-default[disabled]:focus, fieldset[disabled] .btn-default:focus, .btn-default.disabled.focus, .btn-default[disabled].focus, fieldset[disabled] .btn-default.focus, .btn-default.disabled:active, .btn-default[disabled]:active, fieldset[disabled] .btn-default:active, .btn-default.disabled.active, .btn-default[disabled].active, fieldset[disabled] .btn-default.active {
background-color: #e0e0e0;
background-image: none
}
.btn-primary {
background-image: -webkit-linear-gradient(top, #337ab7 0, #265a88 100%);
background-image: -o-linear-gradient(top, #337ab7 0, #265a88 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #337ab7), to(#265a88));
background-image: linear-gradient(to bottom, #337ab7 0, #265a88 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
background-repeat: repeat-x;
border-color: #245580
}
.btn-primary:hover, .btn-primary:focus {
background-color: #265a88;
background-position: 0 -15px
}
.btn-primary:active, .btn-primary.active {
background-color: #265a88;
border-color: #245580
}
.btn-primary.disabled, .btn-primary[disabled], fieldset[disabled] .btn-primary, .btn-primary.disabled:hover, .btn-primary[disabled]:hover, fieldset[disabled] .btn-primary:hover, .btn-primary.disabled:focus, .btn-primary[disabled]:focus, fieldset[disabled] .btn-primary:focus, .btn-primary.disabled.focus, .btn-primary[disabled].focus, fieldset[disabled] .btn-primary.focus, .btn-primary.disabled:active, .btn-primary[disabled]:active, fieldset[disabled] .btn-primary:active, .btn-primary.disabled.active, .btn-primary[disabled].active, fieldset[disabled] .btn-primary.active {
background-color: #265a88;
background-image: none
}
.btn-success {
background-image: -webkit-linear-gradient(top, #5cb85c 0, #419641 100%);
background-image: -o-linear-gradient(top, #5cb85c 0, #419641 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #5cb85c), to(#419641));
background-image: linear-gradient(to bottom, #5cb85c 0, #419641 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
background-repeat: repeat-x;
border-color: #3e8f3e
}
.btn-success:hover, .btn-success:focus {
background-color: #419641;
background-position: 0 -15px
}
.btn-success:active, .btn-success.active {
background-color: #419641;
border-color: #3e8f3e
}
.btn-success.disabled, .btn-success[disabled], fieldset[disabled] .btn-success, .btn-success.disabled:hover, .btn-success[disabled]:hover, fieldset[disabled] .btn-success:hover, .btn-success.disabled:focus, .btn-success[disabled]:focus, fieldset[disabled] .btn-success:focus, .btn-success.disabled.focus, .btn-success[disabled].focus, fieldset[disabled] .btn-success.focus, .btn-success.disabled:active, .btn-success[disabled]:active, fieldset[disabled] .btn-success:active, .btn-success.disabled.active, .btn-success[disabled].active, fieldset[disabled] .btn-success.active {
background-color: #419641;
background-image: none
}
.btn-info {
background-image: -webkit-linear-gradient(top, #5bc0de 0, #2aabd2 100%);
background-image: -o-linear-gradient(top, #5bc0de 0, #2aabd2 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #5bc0de), to(#2aabd2));
background-image: linear-gradient(to bottom, #5bc0de 0, #2aabd2 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
background-repeat: repeat-x;
border-color: #28a4c9
}
.btn-info:hover, .btn-info:focus {
background-color: #2aabd2;
background-position: 0 -15px
}
.btn-info:active, .btn-info.active {
background-color: #2aabd2;
border-color: #28a4c9
}
.btn-info.disabled, .btn-info[disabled], fieldset[disabled] .btn-info, .btn-info.disabled:hover, .btn-info[disabled]:hover, fieldset[disabled] .btn-info:hover, .btn-info.disabled:focus, .btn-info[disabled]:focus, fieldset[disabled] .btn-info:focus, .btn-info.disabled.focus, .btn-info[disabled].focus, fieldset[disabled] .btn-info.focus, .btn-info.disabled:active, .btn-info[disabled]:active, fieldset[disabled] .btn-info:active, .btn-info.disabled.active, .btn-info[disabled].active, fieldset[disabled] .btn-info.active {
background-color: #2aabd2;
background-image: none
}
.btn-warning {
background-image: -webkit-linear-gradient(top, #f0ad4e 0, #eb9316 100%);
background-image: -o-linear-gradient(top, #f0ad4e 0, #eb9316 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #f0ad4e), to(#eb9316));
background-image: linear-gradient(to bottom, #f0ad4e 0, #eb9316 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
background-repeat: repeat-x;
border-color: #e38d13
}
.btn-warning:hover, .btn-warning:focus {
background-color: #eb9316;
background-position: 0 -15px
}
.btn-warning:active, .btn-warning.active {
background-color: #eb9316;
border-color: #e38d13
}
.btn-warning.disabled, .btn-warning[disabled], fieldset[disabled] .btn-warning, .btn-warning.disabled:hover, .btn-warning[disabled]:hover, fieldset[disabled] .btn-warning:hover, .btn-warning.disabled:focus, .btn-warning[disabled]:focus, fieldset[disabled] .btn-warning:focus, .btn-warning.disabled.focus, .btn-warning[disabled].focus, fieldset[disabled] .btn-warning.focus, .btn-warning.disabled:active, .btn-warning[disabled]:active, fieldset[disabled] .btn-warning:active, .btn-warning.disabled.active, .btn-warning[disabled].active, fieldset[disabled] .btn-warning.active {
background-color: #eb9316;
background-image: none
}
.btn-danger {
background-image: -webkit-linear-gradient(top, #d9534f 0, #c12e2a 100%);
background-image: -o-linear-gradient(top, #d9534f 0, #c12e2a 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #d9534f), to(#c12e2a));
background-image: linear-gradient(to bottom, #d9534f 0, #c12e2a 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
background-repeat: repeat-x;
border-color: #b92c28
}
.btn-danger:hover, .btn-danger:focus {
background-color: #c12e2a;
background-position: 0 -15px
}
.btn-danger:active, .btn-danger.active {
background-color: #c12e2a;
border-color: #b92c28
}
.btn-danger.disabled, .btn-danger[disabled], fieldset[disabled] .btn-danger, .btn-danger.disabled:hover, .btn-danger[disabled]:hover, fieldset[disabled] .btn-danger:hover, .btn-danger.disabled:focus, .btn-danger[disabled]:focus, fieldset[disabled] .btn-danger:focus, .btn-danger.disabled.focus, .btn-danger[disabled].focus, fieldset[disabled] .btn-danger.focus, .btn-danger.disabled:active, .btn-danger[disabled]:active, fieldset[disabled] .btn-danger:active, .btn-danger.disabled.active, .btn-danger[disabled].active, fieldset[disabled] .btn-danger.active {
background-color: #c12e2a;
background-image: none
}
.thumbnail, .img-thumbnail {
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075)
}
.dropdown-menu > li > a:hover, .dropdown-menu > li > a:focus {
background-image: -webkit-linear-gradient(top, #f5f5f5 0, #e8e8e8 100%);
background-image: -o-linear-gradient(top, #f5f5f5 0, #e8e8e8 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #f5f5f5), to(#e8e8e8));
background-image: linear-gradient(to bottom, #f5f5f5 0, #e8e8e8 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
background-color: #e8e8e8
}
.dropdown-menu > .active > a, .dropdown-menu > .active > a:hover, .dropdown-menu > .active > a:focus {
background-image: -webkit-linear-gradient(top, #337ab7 0, #2e6da4 100%);
background-image: -o-linear-gradient(top, #337ab7 0, #2e6da4 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #337ab7), to(#2e6da4));
background-image: linear-gradient(to bottom, #337ab7 0, #2e6da4 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
background-color: #2e6da4
}
.navbar-default {
background-image: -webkit-linear-gradient(top, #fff 0, #f8f8f8 100%);
background-image: -o-linear-gradient(top, #fff 0, #f8f8f8 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #fff), to(#f8f8f8));
background-image: linear-gradient(to bottom, #fff 0, #f8f8f8 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075)
}
.navbar-default .navbar-nav > .open > a, .navbar-default .navbar-nav > .active > a {
background-image: -webkit-linear-gradient(top, #dbdbdb 0, #e2e2e2 100%);
background-image: -o-linear-gradient(top, #dbdbdb 0, #e2e2e2 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #dbdbdb), to(#e2e2e2));
background-image: linear-gradient(to bottom, #dbdbdb 0, #e2e2e2 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075)
}
.navbar-brand, .navbar-nav > li > a {
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25)
}
.navbar-inverse {
background-image: -webkit-linear-gradient(top, #3c3c3c 0, #222 100%);
background-image: -o-linear-gradient(top, #3c3c3c 0, #222 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #3c3c3c), to(#222));
background-image: linear-gradient(to bottom, #3c3c3c 0, #222 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
border-radius: 4px
}
.navbar-inverse .navbar-nav > .open > a, .navbar-inverse .navbar-nav > .active > a {
background-image: -webkit-linear-gradient(top, #080808 0, #0f0f0f 100%);
background-image: -o-linear-gradient(top, #080808 0, #0f0f0f 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #080808), to(#0f0f0f));
background-image: linear-gradient(to bottom, #080808 0, #0f0f0f 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);
box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25)
}
.navbar-inverse .navbar-brand, .navbar-inverse .navbar-nav > li > a {
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25)
}
.navbar-static-top, .navbar-fixed-top, .navbar-fixed-bottom {
border-radius: 0
}
@media (max-width: 767px) {
.navbar .navbar-nav .open .dropdown-menu > .active > a, .navbar .navbar-nav .open .dropdown-menu > .active > a:hover, .navbar .navbar-nav .open .dropdown-menu > .active > a:focus {
color: #fff;
background-image: -webkit-linear-gradient(top, #337ab7 0, #2e6da4 100%);
background-image: -o-linear-gradient(top, #337ab7 0, #2e6da4 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #337ab7), to(#2e6da4));
background-image: linear-gradient(to bottom, #337ab7 0, #2e6da4 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0)
}
}
.alert {
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05)
}
.alert-success {
background-image: -webkit-linear-gradient(top, #dff0d8 0, #c8e5bc 100%);
background-image: -o-linear-gradient(top, #dff0d8 0, #c8e5bc 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #dff0d8), to(#c8e5bc));
background-image: linear-gradient(to bottom, #dff0d8 0, #c8e5bc 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
border-color: #b2dba1
}
.alert-info {
background-image: -webkit-linear-gradient(top, #d9edf7 0, #b9def0 100%);
background-image: -o-linear-gradient(top, #d9edf7 0, #b9def0 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #d9edf7), to(#b9def0));
background-image: linear-gradient(to bottom, #d9edf7 0, #b9def0 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
border-color: #9acfea
}
.alert-warning {
background-image: -webkit-linear-gradient(top, #fcf8e3 0, #f8efc0 100%);
background-image: -o-linear-gradient(top, #fcf8e3 0, #f8efc0 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #fcf8e3), to(#f8efc0));
background-image: linear-gradient(to bottom, #fcf8e3 0, #f8efc0 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
border-color: #f5e79e
}
.alert-danger {
background-image: -webkit-linear-gradient(top, #f2dede 0, #e7c3c3 100%);
background-image: -o-linear-gradient(top, #f2dede 0, #e7c3c3 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #f2dede), to(#e7c3c3));
background-image: linear-gradient(to bottom, #f2dede 0, #e7c3c3 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
border-color: #dca7a7
}
.progress {
background-image: -webkit-linear-gradient(top, #ebebeb 0, #f5f5f5 100%);
background-image: -o-linear-gradient(top, #ebebeb 0, #f5f5f5 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #ebebeb), to(#f5f5f5));
background-image: linear-gradient(to bottom, #ebebeb 0, #f5f5f5 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0)
}
.progress-bar {
background-image: -webkit-linear-gradient(top, #337ab7 0, #286090 100%);
background-image: -o-linear-gradient(top, #337ab7 0, #286090 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #337ab7), to(#286090));
background-image: linear-gradient(to bottom, #337ab7 0, #286090 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0)
}
.progress-bar-success {
background-image: -webkit-linear-gradient(top, #5cb85c 0, #449d44 100%);
background-image: -o-linear-gradient(top, #5cb85c 0, #449d44 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #5cb85c), to(#449d44));
background-image: linear-gradient(to bottom, #5cb85c 0, #449d44 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0)
}
.progress-bar-info {
background-image: -webkit-linear-gradient(top, #5bc0de 0, #31b0d5 100%);
background-image: -o-linear-gradient(top, #5bc0de 0, #31b0d5 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #5bc0de), to(#31b0d5));
background-image: linear-gradient(to bottom, #5bc0de 0, #31b0d5 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0)
}
.progress-bar-warning {
background-image: -webkit-linear-gradient(top, #f0ad4e 0, #ec971f 100%);
background-image: -o-linear-gradient(top, #f0ad4e 0, #ec971f 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #f0ad4e), to(#ec971f));
background-image: linear-gradient(to bottom, #f0ad4e 0, #ec971f 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0)
}
.progress-bar-danger {
background-image: -webkit-linear-gradient(top, #d9534f 0, #c9302c 100%);
background-image: -o-linear-gradient(top, #d9534f 0, #c9302c 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #d9534f), to(#c9302c));
background-image: linear-gradient(to bottom, #d9534f 0, #c9302c 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0)
}
.progress-bar-striped {
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent)
}
.list-group {
border-radius: 4px;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075)
}
.list-group-item.active, .list-group-item.active:hover, .list-group-item.active:focus {
text-shadow: 0 -1px 0 #286090;
background-image: -webkit-linear-gradient(top, #337ab7 0, #2b669a 100%);
background-image: -o-linear-gradient(top, #337ab7 0, #2b669a 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #337ab7), to(#2b669a));
background-image: linear-gradient(to bottom, #337ab7 0, #2b669a 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);
border-color: #2b669a
}
.list-group-item.active .badge, .list-group-item.active:hover .badge, .list-group-item.active:focus .badge {
text-shadow: none
}
.panel {
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05)
}
.panel-default > .panel-heading {
background-image: -webkit-linear-gradient(top, #f5f5f5 0, #e8e8e8 100%);
background-image: -o-linear-gradient(top, #f5f5f5 0, #e8e8e8 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #f5f5f5), to(#e8e8e8));
background-image: linear-gradient(to bottom, #f5f5f5 0, #e8e8e8 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0)
}
.panel-primary > .panel-heading {
background-image: -webkit-linear-gradient(top, #337ab7 0, #2e6da4 100%);
background-image: -o-linear-gradient(top, #337ab7 0, #2e6da4 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #337ab7), to(#2e6da4));
background-image: linear-gradient(to bottom, #337ab7 0, #2e6da4 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0)
}
.panel-success > .panel-heading {
background-image: -webkit-linear-gradient(top, #dff0d8 0, #d0e9c6 100%);
background-image: -o-linear-gradient(top, #dff0d8 0, #d0e9c6 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #dff0d8), to(#d0e9c6));
background-image: linear-gradient(to bottom, #dff0d8 0, #d0e9c6 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0)
}
.panel-info > .panel-heading {
background-image: -webkit-linear-gradient(top, #d9edf7 0, #c4e3f3 100%);
background-image: -o-linear-gradient(top, #d9edf7 0, #c4e3f3 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #d9edf7), to(#c4e3f3));
background-image: linear-gradient(to bottom, #d9edf7 0, #c4e3f3 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0)
}
.panel-warning > .panel-heading {
background-image: -webkit-linear-gradient(top, #fcf8e3 0, #faf2cc 100%);
background-image: -o-linear-gradient(top, #fcf8e3 0, #faf2cc 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #fcf8e3), to(#faf2cc));
background-image: linear-gradient(to bottom, #fcf8e3 0, #faf2cc 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0)
}
.panel-danger > .panel-heading {
background-image: -webkit-linear-gradient(top, #f2dede 0, #ebcccc 100%);
background-image: -o-linear-gradient(top, #f2dede 0, #ebcccc 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #f2dede), to(#ebcccc));
background-image: linear-gradient(to bottom, #f2dede 0, #ebcccc 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0)
}
.well {
background-image: -webkit-linear-gradient(top, #e8e8e8 0, #f5f5f5 100%);
background-image: -o-linear-gradient(top, #e8e8e8 0, #f5f5f5 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #e8e8e8), to(#f5f5f5));
background-image: linear-gradient(to bottom, #e8e8e8 0, #f5f5f5 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
border-color: #dcdcdc;
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1)
}
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -8,5 +8,781 @@ ...@@ -8,5 +8,781 @@
* Generated using the Bootstrap Customizer (http://v3.bootcss.com/customize/?id=822d18dc2e4e823a577b) * Generated using the Bootstrap Customizer (http://v3.bootcss.com/customize/?id=822d18dc2e4e823a577b)
* Config saved to config.json and https://gist.github.com/822d18dc2e4e823a577b * Config saved to config.json and https://gist.github.com/822d18dc2e4e823a577b
*/ */
if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(t){"use strict";var e=t.fn.jquery.split(" ")[0].split(".");if(e[0]<2&&e[1]<9||1==e[0]&&9==e[1]&&e[2]<1)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher")}(jQuery),+function(t){"use strict";function e(e){return this.each(function(){var i=t(this),n=i.data("bs.alert");n||i.data("bs.alert",n=new o(this)),"string"==typeof e&&n[e].call(i)})}var i='[data-dismiss="alert"]',o=function(e){t(e).on("click",i,this.close)};o.VERSION="3.3.5",o.TRANSITION_DURATION=150,o.prototype.close=function(e){function i(){a.detach().trigger("closed.bs.alert").remove()}var n=t(this),s=n.attr("data-target");s||(s=n.attr("href"),s=s&&s.replace(/.*(?=#[^\s]*$)/,""));var a=t(s);e&&e.preventDefault(),a.length||(a=n.closest(".alert")),a.trigger(e=t.Event("close.bs.alert")),e.isDefaultPrevented()||(a.removeClass("in"),t.support.transition&&a.hasClass("fade")?a.one("bsTransitionEnd",i).emulateTransitionEnd(o.TRANSITION_DURATION):i())};var n=t.fn.alert;t.fn.alert=e,t.fn.alert.Constructor=o,t.fn.alert.noConflict=function(){return t.fn.alert=n,this},t(document).on("click.bs.alert.data-api",i,o.prototype.close)}(jQuery),+function(t){"use strict";function e(e){return this.each(function(){var o=t(this),n=o.data("bs.button"),s="object"==typeof e&&e;n||o.data("bs.button",n=new i(this,s)),"toggle"==e?n.toggle():e&&n.setState(e)})}var i=function(e,o){this.$element=t(e),this.options=t.extend({},i.DEFAULTS,o),this.isLoading=!1};i.VERSION="3.3.5",i.DEFAULTS={loadingText:"loading..."},i.prototype.setState=function(e){var i="disabled",o=this.$element,n=o.is("input")?"val":"html",s=o.data();e+="Text",null==s.resetText&&o.data("resetText",o[n]()),setTimeout(t.proxy(function(){o[n](null==s[e]?this.options[e]:s[e]),"loadingText"==e?(this.isLoading=!0,o.addClass(i).attr(i,i)):this.isLoading&&(this.isLoading=!1,o.removeClass(i).removeAttr(i))},this),0)},i.prototype.toggle=function(){var t=!0,e=this.$element.closest('[data-toggle="buttons"]');if(e.length){var i=this.$element.find("input");"radio"==i.prop("type")?(i.prop("checked")&&(t=!1),e.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==i.prop("type")&&(i.prop("checked")!==this.$element.hasClass("active")&&(t=!1),this.$element.toggleClass("active")),i.prop("checked",this.$element.hasClass("active")),t&&i.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var o=t.fn.button;t.fn.button=e,t.fn.button.Constructor=i,t.fn.button.noConflict=function(){return t.fn.button=o,this},t(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(i){var o=t(i.target);o.hasClass("btn")||(o=o.closest(".btn")),e.call(o,"toggle"),t(i.target).is('input[type="radio"]')||t(i.target).is('input[type="checkbox"]')||i.preventDefault()}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(e){t(e.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(e.type))})}(jQuery),+function(t){"use strict";function e(e){return this.each(function(){var o=t(this),n=o.data("bs.carousel"),s=t.extend({},i.DEFAULTS,o.data(),"object"==typeof e&&e),a="string"==typeof e?e:s.slide;n||o.data("bs.carousel",n=new i(this,s)),"number"==typeof e?n.to(e):a?n[a]():s.interval&&n.pause().cycle()})}var i=function(e,i){this.$element=t(e),this.$indicators=this.$element.find(".carousel-indicators"),this.options=i,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",t.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",t.proxy(this.pause,this)).on("mouseleave.bs.carousel",t.proxy(this.cycle,this))};i.VERSION="3.3.5",i.TRANSITION_DURATION=600,i.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},i.prototype.keydown=function(t){if(!/input|textarea/i.test(t.target.tagName)){switch(t.which){case 37:this.prev();break;case 39:this.next();break;default:return}t.preventDefault()}},i.prototype.cycle=function(e){return e||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(t.proxy(this.next,this),this.options.interval)),this},i.prototype.getItemIndex=function(t){return this.$items=t.parent().children(".item"),this.$items.index(t||this.$active)},i.prototype.getItemForDirection=function(t,e){var i=this.getItemIndex(e),o="prev"==t&&0===i||"next"==t&&i==this.$items.length-1;if(o&&!this.options.wrap)return e;var n="prev"==t?-1:1,s=(i+n)%this.$items.length;return this.$items.eq(s)},i.prototype.to=function(t){var e=this,i=this.getItemIndex(this.$active=this.$element.find(".item.active"));return t>this.$items.length-1||0>t?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){e.to(t)}):i==t?this.pause().cycle():this.slide(t>i?"next":"prev",this.$items.eq(t))},i.prototype.pause=function(e){return e||(this.paused=!0),this.$element.find(".next, .prev").length&&t.support.transition&&(this.$element.trigger(t.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},i.prototype.next=function(){return this.sliding?void 0:this.slide("next")},i.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},i.prototype.slide=function(e,o){var n=this.$element.find(".item.active"),s=o||this.getItemForDirection(e,n),a=this.interval,r="next"==e?"left":"right",l=this;if(s.hasClass("active"))return this.sliding=!1;var h=s[0],d=t.Event("slide.bs.carousel",{relatedTarget:h,direction:r});if(this.$element.trigger(d),!d.isDefaultPrevented()){if(this.sliding=!0,a&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var p=t(this.$indicators.children()[this.getItemIndex(s)]);p&&p.addClass("active")}var c=t.Event("slid.bs.carousel",{relatedTarget:h,direction:r});return t.support.transition&&this.$element.hasClass("slide")?(s.addClass(e),s[0].offsetWidth,n.addClass(r),s.addClass(r),n.one("bsTransitionEnd",function(){s.removeClass([e,r].join(" ")).addClass("active"),n.removeClass(["active",r].join(" ")),l.sliding=!1,setTimeout(function(){l.$element.trigger(c)},0)}).emulateTransitionEnd(i.TRANSITION_DURATION)):(n.removeClass("active"),s.addClass("active"),this.sliding=!1,this.$element.trigger(c)),a&&this.cycle(),this}};var o=t.fn.carousel;t.fn.carousel=e,t.fn.carousel.Constructor=i,t.fn.carousel.noConflict=function(){return t.fn.carousel=o,this};var n=function(i){var o,n=t(this),s=t(n.attr("data-target")||(o=n.attr("href"))&&o.replace(/.*(?=#[^\s]+$)/,""));if(s.hasClass("carousel")){var a=t.extend({},s.data(),n.data()),r=n.attr("data-slide-to");r&&(a.interval=!1),e.call(s,a),r&&s.data("bs.carousel").to(r),i.preventDefault()}};t(document).on("click.bs.carousel.data-api","[data-slide]",n).on("click.bs.carousel.data-api","[data-slide-to]",n),t(window).on("load",function(){t('[data-ride="carousel"]').each(function(){var i=t(this);e.call(i,i.data())})})}(jQuery),+function(t){"use strict";function e(e){var i=e.attr("data-target");i||(i=e.attr("href"),i=i&&/#[A-Za-z]/.test(i)&&i.replace(/.*(?=#[^\s]*$)/,""));var o=i&&t(i);return o&&o.length?o:e.parent()}function i(i){i&&3===i.which||(t(n).remove(),t(s).each(function(){var o=t(this),n=e(o),s={relatedTarget:this};n.hasClass("open")&&(i&&"click"==i.type&&/input|textarea/i.test(i.target.tagName)&&t.contains(n[0],i.target)||(n.trigger(i=t.Event("hide.bs.dropdown",s)),i.isDefaultPrevented()||(o.attr("aria-expanded","false"),n.removeClass("open").trigger("hidden.bs.dropdown",s))))}))}function o(e){return this.each(function(){var i=t(this),o=i.data("bs.dropdown");o||i.data("bs.dropdown",o=new a(this)),"string"==typeof e&&o[e].call(i)})}var n=".dropdown-backdrop",s='[data-toggle="dropdown"]',a=function(e){t(e).on("click.bs.dropdown",this.toggle)};a.VERSION="3.3.5",a.prototype.toggle=function(o){var n=t(this);if(!n.is(".disabled, :disabled")){var s=e(n),a=s.hasClass("open");if(i(),!a){"ontouchstart"in document.documentElement&&!s.closest(".navbar-nav").length&&t(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(t(this)).on("click",i);var r={relatedTarget:this};if(s.trigger(o=t.Event("show.bs.dropdown",r)),o.isDefaultPrevented())return;n.trigger("focus").attr("aria-expanded","true"),s.toggleClass("open").trigger("shown.bs.dropdown",r)}return!1}},a.prototype.keydown=function(i){if(/(38|40|27|32)/.test(i.which)&&!/input|textarea/i.test(i.target.tagName)){var o=t(this);if(i.preventDefault(),i.stopPropagation(),!o.is(".disabled, :disabled")){var n=e(o),a=n.hasClass("open");if(!a&&27!=i.which||a&&27==i.which)return 27==i.which&&n.find(s).trigger("focus"),o.trigger("click");var r=" li:not(.disabled):visible a",l=n.find(".dropdown-menu"+r);if(l.length){var h=l.index(i.target);38==i.which&&h>0&&h--,40==i.which&&h<l.length-1&&h++,~h||(h=0),l.eq(h).trigger("focus")}}}};var r=t.fn.dropdown;t.fn.dropdown=o,t.fn.dropdown.Constructor=a,t.fn.dropdown.noConflict=function(){return t.fn.dropdown=r,this},t(document).on("click.bs.dropdown.data-api",i).on("click.bs.dropdown.data-api",".dropdown form",function(t){t.stopPropagation()}).on("click.bs.dropdown.data-api",s,a.prototype.toggle).on("keydown.bs.dropdown.data-api",s,a.prototype.keydown).on("keydown.bs.dropdown.data-api",".dropdown-menu",a.prototype.keydown)}(jQuery),+function(t){"use strict";function e(e,o){return this.each(function(){var n=t(this),s=n.data("bs.modal"),a=t.extend({},i.DEFAULTS,n.data(),"object"==typeof e&&e);s||n.data("bs.modal",s=new i(this,a)),"string"==typeof e?s[e](o):a.show&&s.show(o)})}var i=function(e,i){this.options=i,this.$body=t(document.body),this.$element=t(e),this.$dialog=this.$element.find(".modal-dialog"),this.$backdrop=null,this.isShown=null,this.originalBodyPad=null,this.scrollbarWidth=0,this.ignoreBackdropClick=!1,this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,t.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};i.VERSION="3.3.5",i.TRANSITION_DURATION=300,i.BACKDROP_TRANSITION_DURATION=150,i.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},i.prototype.toggle=function(t){return this.isShown?this.hide():this.show(t)},i.prototype.show=function(e){var o=this,n=t.Event("show.bs.modal",{relatedTarget:e});this.$element.trigger(n),this.isShown||n.isDefaultPrevented()||(this.isShown=!0,this.checkScrollbar(),this.setScrollbar(),this.$body.addClass("modal-open"),this.escape(),this.resize(),this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',t.proxy(this.hide,this)),this.$dialog.on("mousedown.dismiss.bs.modal",function(){o.$element.one("mouseup.dismiss.bs.modal",function(e){t(e.target).is(o.$element)&&(o.ignoreBackdropClick=!0)})}),this.backdrop(function(){var n=t.support.transition&&o.$element.hasClass("fade");o.$element.parent().length||o.$element.appendTo(o.$body),o.$element.show().scrollTop(0),o.adjustDialog(),n&&o.$element[0].offsetWidth,o.$element.addClass("in"),o.enforceFocus();var s=t.Event("shown.bs.modal",{relatedTarget:e});n?o.$dialog.one("bsTransitionEnd",function(){o.$element.trigger("focus").trigger(s)}).emulateTransitionEnd(i.TRANSITION_DURATION):o.$element.trigger("focus").trigger(s)}))},i.prototype.hide=function(e){e&&e.preventDefault(),e=t.Event("hide.bs.modal"),this.$element.trigger(e),this.isShown&&!e.isDefaultPrevented()&&(this.isShown=!1,this.escape(),this.resize(),t(document).off("focusin.bs.modal"),this.$element.removeClass("in").off("click.dismiss.bs.modal").off("mouseup.dismiss.bs.modal"),this.$dialog.off("mousedown.dismiss.bs.modal"),t.support.transition&&this.$element.hasClass("fade")?this.$element.one("bsTransitionEnd",t.proxy(this.hideModal,this)).emulateTransitionEnd(i.TRANSITION_DURATION):this.hideModal())},i.prototype.enforceFocus=function(){t(document).off("focusin.bs.modal").on("focusin.bs.modal",t.proxy(function(t){this.$element[0]===t.target||this.$element.has(t.target).length||this.$element.trigger("focus")},this))},i.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keydown.dismiss.bs.modal",t.proxy(function(t){27==t.which&&this.hide()},this)):this.isShown||this.$element.off("keydown.dismiss.bs.modal")},i.prototype.resize=function(){this.isShown?t(window).on("resize.bs.modal",t.proxy(this.handleUpdate,this)):t(window).off("resize.bs.modal")},i.prototype.hideModal=function(){var t=this;this.$element.hide(),this.backdrop(function(){t.$body.removeClass("modal-open"),t.resetAdjustments(),t.resetScrollbar(),t.$element.trigger("hidden.bs.modal")})},i.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},i.prototype.backdrop=function(e){var o=this,n=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var s=t.support.transition&&n;if(this.$backdrop=t(document.createElement("div")).addClass("modal-backdrop "+n).appendTo(this.$body),this.$element.on("click.dismiss.bs.modal",t.proxy(function(t){return this.ignoreBackdropClick?void(this.ignoreBackdropClick=!1):void(t.target===t.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus():this.hide()))},this)),s&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!e)return;s?this.$backdrop.one("bsTransitionEnd",e).emulateTransitionEnd(i.BACKDROP_TRANSITION_DURATION):e()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var a=function(){o.removeBackdrop(),e&&e()};t.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",a).emulateTransitionEnd(i.BACKDROP_TRANSITION_DURATION):a()}else e&&e()},i.prototype.handleUpdate=function(){this.adjustDialog()},i.prototype.adjustDialog=function(){var t=this.$element[0].scrollHeight>document.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&t?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!t?this.scrollbarWidth:""})},i.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},i.prototype.checkScrollbar=function(){var t=window.innerWidth;if(!t){var e=document.documentElement.getBoundingClientRect();t=e.right-Math.abs(e.left)}this.bodyIsOverflowing=document.body.clientWidth<t,this.scrollbarWidth=this.measureScrollbar()},i.prototype.setScrollbar=function(){var t=parseInt(this.$body.css("padding-right")||0,10);this.originalBodyPad=document.body.style.paddingRight||"",this.bodyIsOverflowing&&this.$body.css("padding-right",t+this.scrollbarWidth)},i.prototype.resetScrollbar=function(){this.$body.css("padding-right",this.originalBodyPad)},i.prototype.measureScrollbar=function(){var t=document.createElement("div");t.className="modal-scrollbar-measure",this.$body.append(t);var e=t.offsetWidth-t.clientWidth;return this.$body[0].removeChild(t),e};var o=t.fn.modal;t.fn.modal=e,t.fn.modal.Constructor=i,t.fn.modal.noConflict=function(){return t.fn.modal=o,this},t(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(i){var o=t(this),n=o.attr("href"),s=t(o.attr("data-target")||n&&n.replace(/.*(?=#[^\s]+$)/,"")),a=s.data("bs.modal")?"toggle":t.extend({remote:!/#/.test(n)&&n},s.data(),o.data());o.is("a")&&i.preventDefault(),s.one("show.bs.modal",function(t){t.isDefaultPrevented()||s.one("hidden.bs.modal",function(){o.is(":visible")&&o.trigger("focus")})}),e.call(s,a,this)})}(jQuery),+function(t){"use strict";function e(e){return this.each(function(){var o=t(this),n=o.data("bs.tooltip"),s="object"==typeof e&&e;(n||!/destroy|hide/.test(e))&&(n||o.data("bs.tooltip",n=new i(this,s)),"string"==typeof e&&n[e]())})}var i=function(t,e){this.type=null,this.options=null,this.enabled=null,this.timeout=null,this.hoverState=null,this.$element=null,this.inState=null,this.init("tooltip",t,e)};i.VERSION="3.3.5",i.TRANSITION_DURATION=150,i.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},i.prototype.init=function(e,i,o){if(this.enabled=!0,this.type=e,this.$element=t(i),this.options=this.getOptions(o),this.$viewport=this.options.viewport&&t(t.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var n=this.options.trigger.split(" "),s=n.length;s--;){var a=n[s];if("click"==a)this.$element.on("click."+this.type,this.options.selector,t.proxy(this.toggle,this));else if("manual"!=a){var r="hover"==a?"mouseenter":"focusin",l="hover"==a?"mouseleave":"focusout";this.$element.on(r+"."+this.type,this.options.selector,t.proxy(this.enter,this)),this.$element.on(l+"."+this.type,this.options.selector,t.proxy(this.leave,this))}}this.options.selector?this._options=t.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},i.prototype.getDefaults=function(){return i.DEFAULTS},i.prototype.getOptions=function(e){return e=t.extend({},this.getDefaults(),this.$element.data(),e),e.delay&&"number"==typeof e.delay&&(e.delay={show:e.delay,hide:e.delay}),e},i.prototype.getDelegateOptions=function(){var e={},i=this.getDefaults();return this._options&&t.each(this._options,function(t,o){i[t]!=o&&(e[t]=o)}),e},i.prototype.enter=function(e){var i=e instanceof this.constructor?e:t(e.currentTarget).data("bs."+this.type);return i||(i=new this.constructor(e.currentTarget,this.getDelegateOptions()),t(e.currentTarget).data("bs."+this.type,i)),e instanceof t.Event&&(i.inState["focusin"==e.type?"focus":"hover"]=!0),i.tip().hasClass("in")||"in"==i.hoverState?void(i.hoverState="in"):(clearTimeout(i.timeout),i.hoverState="in",i.options.delay&&i.options.delay.show?void(i.timeout=setTimeout(function(){"in"==i.hoverState&&i.show()},i.options.delay.show)):i.show())},i.prototype.isInStateTrue=function(){for(var t in this.inState)if(this.inState[t])return!0;return!1},i.prototype.leave=function(e){var i=e instanceof this.constructor?e:t(e.currentTarget).data("bs."+this.type);return i||(i=new this.constructor(e.currentTarget,this.getDelegateOptions()),t(e.currentTarget).data("bs."+this.type,i)),e instanceof t.Event&&(i.inState["focusout"==e.type?"focus":"hover"]=!1),i.isInStateTrue()?void 0:(clearTimeout(i.timeout),i.hoverState="out",i.options.delay&&i.options.delay.hide?void(i.timeout=setTimeout(function(){"out"==i.hoverState&&i.hide()},i.options.delay.hide)):i.hide())},i.prototype.show=function(){var e=t.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(e);var o=t.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(e.isDefaultPrevented()||!o)return;var n=this,s=this.tip(),a=this.getUID(this.type);this.setContent(),s.attr("id",a),this.$element.attr("aria-describedby",a),this.options.animation&&s.addClass("fade");var r="function"==typeof this.options.placement?this.options.placement.call(this,s[0],this.$element[0]):this.options.placement,l=/\s?auto?\s?/i,h=l.test(r);h&&(r=r.replace(l,"")||"top"),s.detach().css({top:0,left:0,display:"block"}).addClass(r).data("bs."+this.type,this),this.options.container?s.appendTo(this.options.container):s.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var d=this.getPosition(),p=s[0].offsetWidth,c=s[0].offsetHeight;if(h){var f=r,u=this.getPosition(this.$viewport);r="bottom"==r&&d.bottom+c>u.bottom?"top":"top"==r&&d.top-c<u.top?"bottom":"right"==r&&d.right+p>u.width?"left":"left"==r&&d.left-p<u.left?"right":r,s.removeClass(f).addClass(r)}var g=this.getCalculatedOffset(r,d,p,c);this.applyPlacement(g,r);var m=function(){var t=n.hoverState;n.$element.trigger("shown.bs."+n.type),n.hoverState=null,"out"==t&&n.leave(n)};t.support.transition&&this.$tip.hasClass("fade")?s.one("bsTransitionEnd",m).emulateTransitionEnd(i.TRANSITION_DURATION):m()}},i.prototype.applyPlacement=function(e,i){var o=this.tip(),n=o[0].offsetWidth,s=o[0].offsetHeight,a=parseInt(o.css("margin-top"),10),r=parseInt(o.css("margin-left"),10);isNaN(a)&&(a=0),isNaN(r)&&(r=0),e.top+=a,e.left+=r,t.offset.setOffset(o[0],t.extend({using:function(t){o.css({top:Math.round(t.top),left:Math.round(t.left)})}},e),0),o.addClass("in");var l=o[0].offsetWidth,h=o[0].offsetHeight;"top"==i&&h!=s&&(e.top=e.top+s-h);var d=this.getViewportAdjustedDelta(i,e,l,h);d.left?e.left+=d.left:e.top+=d.top;var p=/top|bottom/.test(i),c=p?2*d.left-n+l:2*d.top-s+h,f=p?"offsetWidth":"offsetHeight";o.offset(e),this.replaceArrow(c,o[0][f],p)},i.prototype.replaceArrow=function(t,e,i){this.arrow().css(i?"left":"top",50*(1-t/e)+"%").css(i?"top":"left","")},i.prototype.setContent=function(){var t=this.tip(),e=this.getTitle();t.find(".tooltip-inner")[this.options.html?"html":"text"](e),t.removeClass("fade in top bottom left right")},i.prototype.hide=function(e){function o(){"in"!=n.hoverState&&s.detach(),n.$element.removeAttr("aria-describedby").trigger("hidden.bs."+n.type),e&&e()}var n=this,s=t(this.$tip),a=t.Event("hide.bs."+this.type);return this.$element.trigger(a),a.isDefaultPrevented()?void 0:(s.removeClass("in"),t.support.transition&&s.hasClass("fade")?s.one("bsTransitionEnd",o).emulateTransitionEnd(i.TRANSITION_DURATION):o(),this.hoverState=null,this)},i.prototype.fixTitle=function(){var t=this.$element;(t.attr("title")||"string"!=typeof t.attr("data-original-title"))&&t.attr("data-original-title",t.attr("title")||"").attr("title","")},i.prototype.hasContent=function(){return this.getTitle()},i.prototype.getPosition=function(e){e=e||this.$element;var i=e[0],o="BODY"==i.tagName,n=i.getBoundingClientRect();null==n.width&&(n=t.extend({},n,{width:n.right-n.left,height:n.bottom-n.top}));var s=o?{top:0,left:0}:e.offset(),a={scroll:o?document.documentElement.scrollTop||document.body.scrollTop:e.scrollTop()},r=o?{width:t(window).width(),height:t(window).height()}:null;return t.extend({},n,a,r,s)},i.prototype.getCalculatedOffset=function(t,e,i,o){return"bottom"==t?{top:e.top+e.height,left:e.left+e.width/2-i/2}:"top"==t?{top:e.top-o,left:e.left+e.width/2-i/2}:"left"==t?{top:e.top+e.height/2-o/2,left:e.left-i}:{top:e.top+e.height/2-o/2,left:e.left+e.width}},i.prototype.getViewportAdjustedDelta=function(t,e,i,o){var n={top:0,left:0};if(!this.$viewport)return n;var s=this.options.viewport&&this.options.viewport.padding||0,a=this.getPosition(this.$viewport);if(/right|left/.test(t)){var r=e.top-s-a.scroll,l=e.top+s-a.scroll+o;r<a.top?n.top=a.top-r:l>a.top+a.height&&(n.top=a.top+a.height-l)}else{var h=e.left-s,d=e.left+s+i;h<a.left?n.left=a.left-h:d>a.right&&(n.left=a.left+a.width-d)}return n},i.prototype.getTitle=function(){var t,e=this.$element,i=this.options;return t=e.attr("data-original-title")||("function"==typeof i.title?i.title.call(e[0]):i.title)},i.prototype.getUID=function(t){do t+=~~(1e6*Math.random());while(document.getElementById(t));return t},i.prototype.tip=function(){if(!this.$tip&&(this.$tip=t(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},i.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},i.prototype.enable=function(){this.enabled=!0},i.prototype.disable=function(){this.enabled=!1},i.prototype.toggleEnabled=function(){this.enabled=!this.enabled},i.prototype.toggle=function(e){var i=this;e&&(i=t(e.currentTarget).data("bs."+this.type),i||(i=new this.constructor(e.currentTarget,this.getDelegateOptions()),t(e.currentTarget).data("bs."+this.type,i))),e?(i.inState.click=!i.inState.click,i.isInStateTrue()?i.enter(i):i.leave(i)):i.tip().hasClass("in")?i.leave(i):i.enter(i)},i.prototype.destroy=function(){var t=this;clearTimeout(this.timeout),this.hide(function(){t.$element.off("."+t.type).removeData("bs."+t.type),t.$tip&&t.$tip.detach(),t.$tip=null,t.$arrow=null,t.$viewport=null})};var o=t.fn.tooltip;t.fn.tooltip=e,t.fn.tooltip.Constructor=i,t.fn.tooltip.noConflict=function(){return t.fn.tooltip=o,this}}(jQuery),+function(t){"use strict";function e(e){return this.each(function(){var o=t(this),n=o.data("bs.popover"),s="object"==typeof e&&e;(n||!/destroy|hide/.test(e))&&(n||o.data("bs.popover",n=new i(this,s)),"string"==typeof e&&n[e]())})}var i=function(t,e){this.init("popover",t,e)};if(!t.fn.tooltip)throw new Error("Popover requires tooltip.js");i.VERSION="3.3.5",i.DEFAULTS=t.extend({},t.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),i.prototype=t.extend({},t.fn.tooltip.Constructor.prototype),i.prototype.constructor=i,i.prototype.getDefaults=function(){return i.DEFAULTS},i.prototype.setContent=function(){var t=this.tip(),e=this.getTitle(),i=this.getContent();t.find(".popover-title")[this.options.html?"html":"text"](e),t.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof i?"html":"append":"text"](i),t.removeClass("fade top bottom left right in"),t.find(".popover-title").html()||t.find(".popover-title").hide()},i.prototype.hasContent=function(){return this.getTitle()||this.getContent()},i.prototype.getContent=function(){var t=this.$element,e=this.options;return t.attr("data-content")||("function"==typeof e.content?e.content.call(t[0]):e.content)},i.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var o=t.fn.popover;t.fn.popover=e,t.fn.popover.Constructor=i,t.fn.popover.noConflict=function(){return t.fn.popover=o,this}}(jQuery),+function(t){"use strict";function e(e){return this.each(function(){var o=t(this),n=o.data("bs.tab");n||o.data("bs.tab",n=new i(this)),"string"==typeof e&&n[e]()})}var i=function(e){this.element=t(e)};i.VERSION="3.3.5",i.TRANSITION_DURATION=150,i.prototype.show=function(){var e=this.element,i=e.closest("ul:not(.dropdown-menu)"),o=e.data("target");if(o||(o=e.attr("href"),o=o&&o.replace(/.*(?=#[^\s]*$)/,"")),!e.parent("li").hasClass("active")){var n=i.find(".active:last a"),s=t.Event("hide.bs.tab",{relatedTarget:e[0]}),a=t.Event("show.bs.tab",{relatedTarget:n[0]});if(n.trigger(s),e.trigger(a),!a.isDefaultPrevented()&&!s.isDefaultPrevented()){var r=t(o);this.activate(e.closest("li"),i),this.activate(r,r.parent(),function(){n.trigger({type:"hidden.bs.tab",relatedTarget:e[0]}),e.trigger({type:"shown.bs.tab",relatedTarget:n[0]})})}}},i.prototype.activate=function(e,o,n){function s(){a.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),e.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),r?(e[0].offsetWidth,e.addClass("in")):e.removeClass("fade"),e.parent(".dropdown-menu").length&&e.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),n&&n()}var a=o.find("> .active"),r=n&&t.support.transition&&(a.length&&a.hasClass("fade")||!!o.find("> .fade").length);a.length&&r?a.one("bsTransitionEnd",s).emulateTransitionEnd(i.TRANSITION_DURATION):s(),a.removeClass("in")};var o=t.fn.tab;t.fn.tab=e,t.fn.tab.Constructor=i,t.fn.tab.noConflict=function(){return t.fn.tab=o,this};var n=function(i){i.preventDefault(),e.call(t(this),"show")};t(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',n).on("click.bs.tab.data-api",'[data-toggle="pill"]',n)}(jQuery),+function(t){"use strict";function e(e){return this.each(function(){var o=t(this),n=o.data("bs.affix"),s="object"==typeof e&&e;n||o.data("bs.affix",n=new i(this,s)),"string"==typeof e&&n[e]()})}var i=function(e,o){this.options=t.extend({},i.DEFAULTS,o),this.$target=t(this.options.target).on("scroll.bs.affix.data-api",t.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",t.proxy(this.checkPositionWithEventLoop,this)),this.$element=t(e),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};i.VERSION="3.3.5",i.RESET="affix affix-top affix-bottom",i.DEFAULTS={offset:0,target:window},i.prototype.getState=function(t,e,i,o){var n=this.$target.scrollTop(),s=this.$element.offset(),a=this.$target.height();if(null!=i&&"top"==this.affixed)return i>n?"top":!1;if("bottom"==this.affixed)return null!=i?n+this.unpin<=s.top?!1:"bottom":t-o>=n+a?!1:"bottom";var r=null==this.affixed,l=r?n:s.top,h=r?a:e;return null!=i&&i>=n?"top":null!=o&&l+h>=t-o?"bottom":!1},i.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(i.RESET).addClass("affix");var t=this.$target.scrollTop(),e=this.$element.offset();return this.pinnedOffset=e.top-t},i.prototype.checkPositionWithEventLoop=function(){setTimeout(t.proxy(this.checkPosition,this),1)},i.prototype.checkPosition=function(){if(this.$element.is(":visible")){var e=this.$element.height(),o=this.options.offset,n=o.top,s=o.bottom,a=Math.max(t(document).height(),t(document.body).height());"object"!=typeof o&&(s=n=o),"function"==typeof n&&(n=o.top(this.$element)),"function"==typeof s&&(s=o.bottom(this.$element));var r=this.getState(a,e,n,s);if(this.affixed!=r){null!=this.unpin&&this.$element.css("top","");var l="affix"+(r?"-"+r:""),h=t.Event(l+".bs.affix");if(this.$element.trigger(h),h.isDefaultPrevented())return;this.affixed=r,this.unpin="bottom"==r?this.getPinnedOffset():null,this.$element.removeClass(i.RESET).addClass(l).trigger(l.replace("affix","affixed")+".bs.affix")}"bottom"==r&&this.$element.offset({top:a-e-s})}};var o=t.fn.affix;t.fn.affix=e,t.fn.affix.Constructor=i,t.fn.affix.noConflict=function(){return t.fn.affix=o,this},t(window).on("load",function(){t('[data-spy="affix"]').each(function(){var i=t(this),o=i.data();o.offset=o.offset||{},null!=o.offsetBottom&&(o.offset.bottom=o.offsetBottom),null!=o.offsetTop&&(o.offset.top=o.offsetTop),e.call(i,o)})})}(jQuery),+function(t){"use strict";function e(e){var i,o=e.attr("data-target")||(i=e.attr("href"))&&i.replace(/.*(?=#[^\s]+$)/,"");return t(o)}function i(e){return this.each(function(){var i=t(this),n=i.data("bs.collapse"),s=t.extend({},o.DEFAULTS,i.data(),"object"==typeof e&&e);!n&&s.toggle&&/show|hide/.test(e)&&(s.toggle=!1),n||i.data("bs.collapse",n=new o(this,s)),"string"==typeof e&&n[e]()})}var o=function(e,i){this.$element=t(e),this.options=t.extend({},o.DEFAULTS,i),this.$trigger=t('[data-toggle="collapse"][href="#'+e.id+'"],[data-toggle="collapse"][data-target="#'+e.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};o.VERSION="3.3.5",o.TRANSITION_DURATION=350,o.DEFAULTS={toggle:!0},o.prototype.dimension=function(){var t=this.$element.hasClass("width");return t?"width":"height"},o.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var e,n=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(n&&n.length&&(e=n.data("bs.collapse"),e&&e.transitioning))){var s=t.Event("show.bs.collapse");if(this.$element.trigger(s),!s.isDefaultPrevented()){n&&n.length&&(i.call(n,"hide"),e||n.data("bs.collapse",null));var a=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[a](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var r=function(){this.$element.removeClass("collapsing").addClass("collapse in")[a](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!t.support.transition)return r.call(this);var l=t.camelCase(["scroll",a].join("-"));this.$element.one("bsTransitionEnd",t.proxy(r,this)).emulateTransitionEnd(o.TRANSITION_DURATION)[a](this.$element[0][l]); if ("undefined" == typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");
}}}},o.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var e=t.Event("hide.bs.collapse");if(this.$element.trigger(e),!e.isDefaultPrevented()){var i=this.dimension();this.$element[i](this.$element[i]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var n=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return t.support.transition?void this.$element[i](0).one("bsTransitionEnd",t.proxy(n,this)).emulateTransitionEnd(o.TRANSITION_DURATION):n.call(this)}}},o.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},o.prototype.getParent=function(){return t(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(t.proxy(function(i,o){var n=t(o);this.addAriaAndCollapsedClass(e(n),n)},this)).end()},o.prototype.addAriaAndCollapsedClass=function(t,e){var i=t.hasClass("in");t.attr("aria-expanded",i),e.toggleClass("collapsed",!i).attr("aria-expanded",i)};var n=t.fn.collapse;t.fn.collapse=i,t.fn.collapse.Constructor=o,t.fn.collapse.noConflict=function(){return t.fn.collapse=n,this},t(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(o){var n=t(this);n.attr("data-target")||o.preventDefault();var s=e(n),a=s.data("bs.collapse"),r=a?"toggle":n.data();i.call(s,r)})}(jQuery),+function(t){"use strict";function e(i,o){this.$body=t(document.body),this.$scrollElement=t(t(i).is(document.body)?window:i),this.options=t.extend({},e.DEFAULTS,o),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",t.proxy(this.process,this)),this.refresh(),this.process()}function i(i){return this.each(function(){var o=t(this),n=o.data("bs.scrollspy"),s="object"==typeof i&&i;n||o.data("bs.scrollspy",n=new e(this,s)),"string"==typeof i&&n[i]()})}e.VERSION="3.3.5",e.DEFAULTS={offset:10},e.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},e.prototype.refresh=function(){var e=this,i="offset",o=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),t.isWindow(this.$scrollElement[0])||(i="position",o=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var e=t(this),n=e.data("target")||e.attr("href"),s=/^#./.test(n)&&t(n);return s&&s.length&&s.is(":visible")&&[[s[i]().top+o,n]]||null}).sort(function(t,e){return t[0]-e[0]}).each(function(){e.offsets.push(this[0]),e.targets.push(this[1])})},e.prototype.process=function(){var t,e=this.$scrollElement.scrollTop()+this.options.offset,i=this.getScrollHeight(),o=this.options.offset+i-this.$scrollElement.height(),n=this.offsets,s=this.targets,a=this.activeTarget;if(this.scrollHeight!=i&&this.refresh(),e>=o)return a!=(t=s[s.length-1])&&this.activate(t);if(a&&e<n[0])return this.activeTarget=null,this.clear();for(t=n.length;t--;)a!=s[t]&&e>=n[t]&&(void 0===n[t+1]||e<n[t+1])&&this.activate(s[t])},e.prototype.activate=function(e){this.activeTarget=e,this.clear();var i=this.selector+'[data-target="'+e+'"],'+this.selector+'[href="'+e+'"]',o=t(i).parents("li").addClass("active");o.parent(".dropdown-menu").length&&(o=o.closest("li.dropdown").addClass("active")),o.trigger("activate.bs.scrollspy")},e.prototype.clear=function(){t(this.selector).parentsUntil(this.options.target,".active").removeClass("active")};var o=t.fn.scrollspy;t.fn.scrollspy=i,t.fn.scrollspy.Constructor=e,t.fn.scrollspy.noConflict=function(){return t.fn.scrollspy=o,this},t(window).on("load.bs.scrollspy.data-api",function(){t('[data-spy="scroll"]').each(function(){var e=t(this);i.call(e,e.data())})})}(jQuery),+function(t){"use strict";function e(){var t=document.createElement("bootstrap"),e={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var i in e)if(void 0!==t.style[i])return{end:e[i]};return!1}t.fn.emulateTransitionEnd=function(e){var i=!1,o=this;t(this).one("bsTransitionEnd",function(){i=!0});var n=function(){i||t(o).trigger(t.support.transition.end)};return setTimeout(n,e),this},t(function(){t.support.transition=e(),t.support.transition&&(t.event.special.bsTransitionEnd={bindType:t.support.transition.end,delegateType:t.support.transition.end,handle:function(e){return t(e.target).is(this)?e.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery); +function (t) {
\ No newline at end of file "use strict";
var e = t.fn.jquery.split(" ")[0].split(".");
if (e[0] < 2 && e[1] < 9 || 1 == e[0] && 9 == e[1] && e[2] < 1)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher")
}(jQuery), +function (t) {
"use strict";
function e(e) {
return this.each(function () {
var i = t(this), n = i.data("bs.alert");
n || i.data("bs.alert", n = new o(this)), "string" == typeof e && n[e].call(i)
})
}
var i = '[data-dismiss="alert"]', o = function (e) {
t(e).on("click", i, this.close)
};
o.VERSION = "3.3.5", o.TRANSITION_DURATION = 150, o.prototype.close = function (e) {
function i() {
a.detach().trigger("closed.bs.alert").remove()
}
var n = t(this), s = n.attr("data-target");
s || (s = n.attr("href"), s = s && s.replace(/.*(?=#[^\s]*$)/, ""));
var a = t(s);
e && e.preventDefault(), a.length || (a = n.closest(".alert")), a.trigger(e = t.Event("close.bs.alert")), e.isDefaultPrevented() || (a.removeClass("in"), t.support.transition && a.hasClass("fade") ? a.one("bsTransitionEnd", i).emulateTransitionEnd(o.TRANSITION_DURATION) : i())
};
var n = t.fn.alert;
t.fn.alert = e, t.fn.alert.Constructor = o, t.fn.alert.noConflict = function () {
return t.fn.alert = n, this
}, t(document).on("click.bs.alert.data-api", i, o.prototype.close)
}(jQuery), +function (t) {
"use strict";
function e(e) {
return this.each(function () {
var o = t(this), n = o.data("bs.button"), s = "object" == typeof e && e;
n || o.data("bs.button", n = new i(this, s)), "toggle" == e ? n.toggle() : e && n.setState(e)
})
}
var i = function (e, o) {
this.$element = t(e), this.options = t.extend({}, i.DEFAULTS, o), this.isLoading = !1
};
i.VERSION = "3.3.5", i.DEFAULTS = {loadingText: "loading..."}, i.prototype.setState = function (e) {
var i = "disabled", o = this.$element, n = o.is("input") ? "val" : "html", s = o.data();
e += "Text", null == s.resetText && o.data("resetText", o[n]()), setTimeout(t.proxy(function () {
o[n](null == s[e] ? this.options[e] : s[e]), "loadingText" == e ? (this.isLoading = !0, o.addClass(i).attr(i, i)) : this.isLoading && (this.isLoading = !1, o.removeClass(i).removeAttr(i))
}, this), 0)
}, i.prototype.toggle = function () {
var t = !0, e = this.$element.closest('[data-toggle="buttons"]');
if (e.length) {
var i = this.$element.find("input");
"radio" == i.prop("type") ? (i.prop("checked") && (t = !1), e.find(".active").removeClass("active"), this.$element.addClass("active")) : "checkbox" == i.prop("type") && (i.prop("checked") !== this.$element.hasClass("active") && (t = !1), this.$element.toggleClass("active")), i.prop("checked", this.$element.hasClass("active")), t && i.trigger("change")
} else this.$element.attr("aria-pressed", !this.$element.hasClass("active")), this.$element.toggleClass("active")
};
var o = t.fn.button;
t.fn.button = e, t.fn.button.Constructor = i, t.fn.button.noConflict = function () {
return t.fn.button = o, this
}, t(document).on("click.bs.button.data-api", '[data-toggle^="button"]', function (i) {
var o = t(i.target);
o.hasClass("btn") || (o = o.closest(".btn")), e.call(o, "toggle"), t(i.target).is('input[type="radio"]') || t(i.target).is('input[type="checkbox"]') || i.preventDefault()
}).on("focus.bs.button.data-api blur.bs.button.data-api", '[data-toggle^="button"]', function (e) {
t(e.target).closest(".btn").toggleClass("focus", /^focus(in)?$/.test(e.type))
})
}(jQuery), +function (t) {
"use strict";
function e(e) {
return this.each(function () {
var o = t(this), n = o.data("bs.carousel"), s = t.extend({}, i.DEFAULTS, o.data(), "object" == typeof e && e), a = "string" == typeof e ? e : s.slide;
n || o.data("bs.carousel", n = new i(this, s)), "number" == typeof e ? n.to(e) : a ? n[a]() : s.interval && n.pause().cycle()
})
}
var i = function (e, i) {
this.$element = t(e), this.$indicators = this.$element.find(".carousel-indicators"), this.options = i, this.paused = null, this.sliding = null, this.interval = null, this.$active = null, this.$items = null, this.options.keyboard && this.$element.on("keydown.bs.carousel", t.proxy(this.keydown, this)), "hover" == this.options.pause && !("ontouchstart" in document.documentElement) && this.$element.on("mouseenter.bs.carousel", t.proxy(this.pause, this)).on("mouseleave.bs.carousel", t.proxy(this.cycle, this))
};
i.VERSION = "3.3.5", i.TRANSITION_DURATION = 600, i.DEFAULTS = {
interval: 5e3,
pause: "hover",
wrap: !0,
keyboard: !0
}, i.prototype.keydown = function (t) {
if (!/input|textarea/i.test(t.target.tagName)) {
switch (t.which) {
case 37:
this.prev();
break;
case 39:
this.next();
break;
default:
return
}
t.preventDefault()
}
}, i.prototype.cycle = function (e) {
return e || (this.paused = !1), this.interval && clearInterval(this.interval), this.options.interval && !this.paused && (this.interval = setInterval(t.proxy(this.next, this), this.options.interval)), this
}, i.prototype.getItemIndex = function (t) {
return this.$items = t.parent().children(".item"), this.$items.index(t || this.$active)
}, i.prototype.getItemForDirection = function (t, e) {
var i = this.getItemIndex(e), o = "prev" == t && 0 === i || "next" == t && i == this.$items.length - 1;
if (o && !this.options.wrap)return e;
var n = "prev" == t ? -1 : 1, s = (i + n) % this.$items.length;
return this.$items.eq(s)
}, i.prototype.to = function (t) {
var e = this, i = this.getItemIndex(this.$active = this.$element.find(".item.active"));
return t > this.$items.length - 1 || 0 > t ? void 0 : this.sliding ? this.$element.one("slid.bs.carousel", function () {
e.to(t)
}) : i == t ? this.pause().cycle() : this.slide(t > i ? "next" : "prev", this.$items.eq(t))
}, i.prototype.pause = function (e) {
return e || (this.paused = !0), this.$element.find(".next, .prev").length && t.support.transition && (this.$element.trigger(t.support.transition.end), this.cycle(!0)), this.interval = clearInterval(this.interval), this
}, i.prototype.next = function () {
return this.sliding ? void 0 : this.slide("next")
}, i.prototype.prev = function () {
return this.sliding ? void 0 : this.slide("prev")
}, i.prototype.slide = function (e, o) {
var n = this.$element.find(".item.active"), s = o || this.getItemForDirection(e, n), a = this.interval, r = "next" == e ? "left" : "right", l = this;
if (s.hasClass("active"))return this.sliding = !1;
var h = s[0], d = t.Event("slide.bs.carousel", {relatedTarget: h, direction: r});
if (this.$element.trigger(d), !d.isDefaultPrevented()) {
if (this.sliding = !0, a && this.pause(), this.$indicators.length) {
this.$indicators.find(".active").removeClass("active");
var p = t(this.$indicators.children()[this.getItemIndex(s)]);
p && p.addClass("active")
}
var c = t.Event("slid.bs.carousel", {relatedTarget: h, direction: r});
return t.support.transition && this.$element.hasClass("slide") ? (s.addClass(e), s[0].offsetWidth, n.addClass(r), s.addClass(r), n.one("bsTransitionEnd", function () {
s.removeClass([e, r].join(" ")).addClass("active"), n.removeClass(["active", r].join(" ")), l.sliding = !1, setTimeout(function () {
l.$element.trigger(c)
}, 0)
}).emulateTransitionEnd(i.TRANSITION_DURATION)) : (n.removeClass("active"), s.addClass("active"), this.sliding = !1, this.$element.trigger(c)), a && this.cycle(), this
}
};
var o = t.fn.carousel;
t.fn.carousel = e, t.fn.carousel.Constructor = i, t.fn.carousel.noConflict = function () {
return t.fn.carousel = o, this
};
var n = function (i) {
var o, n = t(this), s = t(n.attr("data-target") || (o = n.attr("href")) && o.replace(/.*(?=#[^\s]+$)/, ""));
if (s.hasClass("carousel")) {
var a = t.extend({}, s.data(), n.data()), r = n.attr("data-slide-to");
r && (a.interval = !1), e.call(s, a), r && s.data("bs.carousel").to(r), i.preventDefault()
}
};
t(document).on("click.bs.carousel.data-api", "[data-slide]", n).on("click.bs.carousel.data-api", "[data-slide-to]", n), t(window).on("load", function () {
t('[data-ride="carousel"]').each(function () {
var i = t(this);
e.call(i, i.data())
})
})
}(jQuery), +function (t) {
"use strict";
function e(e) {
var i = e.attr("data-target");
i || (i = e.attr("href"), i = i && /#[A-Za-z]/.test(i) && i.replace(/.*(?=#[^\s]*$)/, ""));
var o = i && t(i);
return o && o.length ? o : e.parent()
}
function i(i) {
i && 3 === i.which || (t(n).remove(), t(s).each(function () {
var o = t(this), n = e(o), s = {relatedTarget: this};
n.hasClass("open") && (i && "click" == i.type && /input|textarea/i.test(i.target.tagName) && t.contains(n[0], i.target) || (n.trigger(i = t.Event("hide.bs.dropdown", s)), i.isDefaultPrevented() || (o.attr("aria-expanded", "false"), n.removeClass("open").trigger("hidden.bs.dropdown", s))))
}))
}
function o(e) {
return this.each(function () {
var i = t(this), o = i.data("bs.dropdown");
o || i.data("bs.dropdown", o = new a(this)), "string" == typeof e && o[e].call(i)
})
}
var n = ".dropdown-backdrop", s = '[data-toggle="dropdown"]', a = function (e) {
t(e).on("click.bs.dropdown", this.toggle)
};
a.VERSION = "3.3.5", a.prototype.toggle = function (o) {
var n = t(this);
if (!n.is(".disabled, :disabled")) {
var s = e(n), a = s.hasClass("open");
if (i(), !a) {
"ontouchstart" in document.documentElement && !s.closest(".navbar-nav").length && t(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(t(this)).on("click", i);
var r = {relatedTarget: this};
if (s.trigger(o = t.Event("show.bs.dropdown", r)), o.isDefaultPrevented())return;
n.trigger("focus").attr("aria-expanded", "true"), s.toggleClass("open").trigger("shown.bs.dropdown", r)
}
return !1
}
}, a.prototype.keydown = function (i) {
if (/(38|40|27|32)/.test(i.which) && !/input|textarea/i.test(i.target.tagName)) {
var o = t(this);
if (i.preventDefault(), i.stopPropagation(), !o.is(".disabled, :disabled")) {
var n = e(o), a = n.hasClass("open");
if (!a && 27 != i.which || a && 27 == i.which)return 27 == i.which && n.find(s).trigger("focus"), o.trigger("click");
var r = " li:not(.disabled):visible a", l = n.find(".dropdown-menu" + r);
if (l.length) {
var h = l.index(i.target);
38 == i.which && h > 0 && h--, 40 == i.which && h < l.length - 1 && h++, ~h || (h = 0), l.eq(h).trigger("focus")
}
}
}
};
var r = t.fn.dropdown;
t.fn.dropdown = o, t.fn.dropdown.Constructor = a, t.fn.dropdown.noConflict = function () {
return t.fn.dropdown = r, this
}, t(document).on("click.bs.dropdown.data-api", i).on("click.bs.dropdown.data-api", ".dropdown form", function (t) {
t.stopPropagation()
}).on("click.bs.dropdown.data-api", s, a.prototype.toggle).on("keydown.bs.dropdown.data-api", s, a.prototype.keydown).on("keydown.bs.dropdown.data-api", ".dropdown-menu", a.prototype.keydown)
}(jQuery), +function (t) {
"use strict";
function e(e, o) {
return this.each(function () {
var n = t(this), s = n.data("bs.modal"), a = t.extend({}, i.DEFAULTS, n.data(), "object" == typeof e && e);
s || n.data("bs.modal", s = new i(this, a)), "string" == typeof e ? s[e](o) : a.show && s.show(o)
})
}
var i = function (e, i) {
this.options = i, this.$body = t(document.body), this.$element = t(e), this.$dialog = this.$element.find(".modal-dialog"), this.$backdrop = null, this.isShown = null, this.originalBodyPad = null, this.scrollbarWidth = 0, this.ignoreBackdropClick = !1, this.options.remote && this.$element.find(".modal-content").load(this.options.remote, t.proxy(function () {
this.$element.trigger("loaded.bs.modal")
}, this))
};
i.VERSION = "3.3.5", i.TRANSITION_DURATION = 300, i.BACKDROP_TRANSITION_DURATION = 150, i.DEFAULTS = {
backdrop: !0,
keyboard: !0,
show: !0
}, i.prototype.toggle = function (t) {
return this.isShown ? this.hide() : this.show(t)
}, i.prototype.show = function (e) {
var o = this, n = t.Event("show.bs.modal", {relatedTarget: e});
this.$element.trigger(n), this.isShown || n.isDefaultPrevented() || (this.isShown = !0, this.checkScrollbar(), this.setScrollbar(), this.$body.addClass("modal-open"), this.escape(), this.resize(), this.$element.on("click.dismiss.bs.modal", '[data-dismiss="modal"]', t.proxy(this.hide, this)), this.$dialog.on("mousedown.dismiss.bs.modal", function () {
o.$element.one("mouseup.dismiss.bs.modal", function (e) {
t(e.target).is(o.$element) && (o.ignoreBackdropClick = !0)
})
}), this.backdrop(function () {
var n = t.support.transition && o.$element.hasClass("fade");
o.$element.parent().length || o.$element.appendTo(o.$body), o.$element.show().scrollTop(0), o.adjustDialog(), n && o.$element[0].offsetWidth, o.$element.addClass("in"), o.enforceFocus();
var s = t.Event("shown.bs.modal", {relatedTarget: e});
n ? o.$dialog.one("bsTransitionEnd", function () {
o.$element.trigger("focus").trigger(s)
}).emulateTransitionEnd(i.TRANSITION_DURATION) : o.$element.trigger("focus").trigger(s)
}))
}, i.prototype.hide = function (e) {
e && e.preventDefault(), e = t.Event("hide.bs.modal"), this.$element.trigger(e), this.isShown && !e.isDefaultPrevented() && (this.isShown = !1, this.escape(), this.resize(), t(document).off("focusin.bs.modal"), this.$element.removeClass("in").off("click.dismiss.bs.modal").off("mouseup.dismiss.bs.modal"), this.$dialog.off("mousedown.dismiss.bs.modal"), t.support.transition && this.$element.hasClass("fade") ? this.$element.one("bsTransitionEnd", t.proxy(this.hideModal, this)).emulateTransitionEnd(i.TRANSITION_DURATION) : this.hideModal())
}, i.prototype.enforceFocus = function () {
t(document).off("focusin.bs.modal").on("focusin.bs.modal", t.proxy(function (t) {
this.$element[0] === t.target || this.$element.has(t.target).length || this.$element.trigger("focus")
}, this))
}, i.prototype.escape = function () {
this.isShown && this.options.keyboard ? this.$element.on("keydown.dismiss.bs.modal", t.proxy(function (t) {
27 == t.which && this.hide()
}, this)) : this.isShown || this.$element.off("keydown.dismiss.bs.modal")
}, i.prototype.resize = function () {
this.isShown ? t(window).on("resize.bs.modal", t.proxy(this.handleUpdate, this)) : t(window).off("resize.bs.modal")
}, i.prototype.hideModal = function () {
var t = this;
this.$element.hide(), this.backdrop(function () {
t.$body.removeClass("modal-open"), t.resetAdjustments(), t.resetScrollbar(), t.$element.trigger("hidden.bs.modal")
})
}, i.prototype.removeBackdrop = function () {
this.$backdrop && this.$backdrop.remove(), this.$backdrop = null
}, i.prototype.backdrop = function (e) {
var o = this, n = this.$element.hasClass("fade") ? "fade" : "";
if (this.isShown && this.options.backdrop) {
var s = t.support.transition && n;
if (this.$backdrop = t(document.createElement("div")).addClass("modal-backdrop " + n).appendTo(this.$body), this.$element.on("click.dismiss.bs.modal", t.proxy(function (t) {
return this.ignoreBackdropClick ? void(this.ignoreBackdropClick = !1) : void(t.target === t.currentTarget && ("static" == this.options.backdrop ? this.$element[0].focus() : this.hide()))
}, this)), s && this.$backdrop[0].offsetWidth, this.$backdrop.addClass("in"), !e)return;
s ? this.$backdrop.one("bsTransitionEnd", e).emulateTransitionEnd(i.BACKDROP_TRANSITION_DURATION) : e()
} else if (!this.isShown && this.$backdrop) {
this.$backdrop.removeClass("in");
var a = function () {
o.removeBackdrop(), e && e()
};
t.support.transition && this.$element.hasClass("fade") ? this.$backdrop.one("bsTransitionEnd", a).emulateTransitionEnd(i.BACKDROP_TRANSITION_DURATION) : a()
} else e && e()
}, i.prototype.handleUpdate = function () {
this.adjustDialog()
}, i.prototype.adjustDialog = function () {
var t = this.$element[0].scrollHeight > document.documentElement.clientHeight;
this.$element.css({
paddingLeft: !this.bodyIsOverflowing && t ? this.scrollbarWidth : "",
paddingRight: this.bodyIsOverflowing && !t ? this.scrollbarWidth : ""
})
}, i.prototype.resetAdjustments = function () {
this.$element.css({paddingLeft: "", paddingRight: ""})
}, i.prototype.checkScrollbar = function () {
var t = window.innerWidth;
if (!t) {
var e = document.documentElement.getBoundingClientRect();
t = e.right - Math.abs(e.left)
}
this.bodyIsOverflowing = document.body.clientWidth < t, this.scrollbarWidth = this.measureScrollbar()
}, i.prototype.setScrollbar = function () {
var t = parseInt(this.$body.css("padding-right") || 0, 10);
this.originalBodyPad = document.body.style.paddingRight || "", this.bodyIsOverflowing && this.$body.css("padding-right", t + this.scrollbarWidth)
}, i.prototype.resetScrollbar = function () {
this.$body.css("padding-right", this.originalBodyPad)
}, i.prototype.measureScrollbar = function () {
var t = document.createElement("div");
t.className = "modal-scrollbar-measure", this.$body.append(t);
var e = t.offsetWidth - t.clientWidth;
return this.$body[0].removeChild(t), e
};
var o = t.fn.modal;
t.fn.modal = e, t.fn.modal.Constructor = i, t.fn.modal.noConflict = function () {
return t.fn.modal = o, this
}, t(document).on("click.bs.modal.data-api", '[data-toggle="modal"]', function (i) {
var o = t(this), n = o.attr("href"), s = t(o.attr("data-target") || n && n.replace(/.*(?=#[^\s]+$)/, "")), a = s.data("bs.modal") ? "toggle" : t.extend({remote: !/#/.test(n) && n}, s.data(), o.data());
o.is("a") && i.preventDefault(), s.one("show.bs.modal", function (t) {
t.isDefaultPrevented() || s.one("hidden.bs.modal", function () {
o.is(":visible") && o.trigger("focus")
})
}), e.call(s, a, this)
})
}(jQuery), +function (t) {
"use strict";
function e(e) {
return this.each(function () {
var o = t(this), n = o.data("bs.tooltip"), s = "object" == typeof e && e;
(n || !/destroy|hide/.test(e)) && (n || o.data("bs.tooltip", n = new i(this, s)), "string" == typeof e && n[e]())
})
}
var i = function (t, e) {
this.type = null, this.options = null, this.enabled = null, this.timeout = null, this.hoverState = null, this.$element = null, this.inState = null, this.init("tooltip", t, e)
};
i.VERSION = "3.3.5", i.TRANSITION_DURATION = 150, i.DEFAULTS = {
animation: !0,
placement: "top",
selector: !1,
template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
trigger: "hover focus",
title: "",
delay: 0,
html: !1,
container: !1,
viewport: {selector: "body", padding: 0}
}, i.prototype.init = function (e, i, o) {
if (this.enabled = !0, this.type = e, this.$element = t(i), this.options = this.getOptions(o), this.$viewport = this.options.viewport && t(t.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : this.options.viewport.selector || this.options.viewport), this.inState = {
click: !1,
hover: !1,
focus: !1
}, this.$element[0] instanceof document.constructor && !this.options.selector)throw new Error("`selector` option must be specified when initializing " + this.type + " on the window.document object!");
for (var n = this.options.trigger.split(" "), s = n.length; s--;) {
var a = n[s];
if ("click" == a)this.$element.on("click." + this.type, this.options.selector, t.proxy(this.toggle, this)); else if ("manual" != a) {
var r = "hover" == a ? "mouseenter" : "focusin", l = "hover" == a ? "mouseleave" : "focusout";
this.$element.on(r + "." + this.type, this.options.selector, t.proxy(this.enter, this)), this.$element.on(l + "." + this.type, this.options.selector, t.proxy(this.leave, this))
}
}
this.options.selector ? this._options = t.extend({}, this.options, {
trigger: "manual",
selector: ""
}) : this.fixTitle()
}, i.prototype.getDefaults = function () {
return i.DEFAULTS
}, i.prototype.getOptions = function (e) {
return e = t.extend({}, this.getDefaults(), this.$element.data(), e), e.delay && "number" == typeof e.delay && (e.delay = {
show: e.delay,
hide: e.delay
}), e
}, i.prototype.getDelegateOptions = function () {
var e = {}, i = this.getDefaults();
return this._options && t.each(this._options, function (t, o) {
i[t] != o && (e[t] = o)
}), e
}, i.prototype.enter = function (e) {
var i = e instanceof this.constructor ? e : t(e.currentTarget).data("bs." + this.type);
return i || (i = new this.constructor(e.currentTarget, this.getDelegateOptions()), t(e.currentTarget).data("bs." + this.type, i)), e instanceof t.Event && (i.inState["focusin" == e.type ? "focus" : "hover"] = !0), i.tip().hasClass("in") || "in" == i.hoverState ? void(i.hoverState = "in") : (clearTimeout(i.timeout), i.hoverState = "in", i.options.delay && i.options.delay.show ? void(i.timeout = setTimeout(function () {
"in" == i.hoverState && i.show()
}, i.options.delay.show)) : i.show())
}, i.prototype.isInStateTrue = function () {
for (var t in this.inState)if (this.inState[t])return !0;
return !1
}, i.prototype.leave = function (e) {
var i = e instanceof this.constructor ? e : t(e.currentTarget).data("bs." + this.type);
return i || (i = new this.constructor(e.currentTarget, this.getDelegateOptions()), t(e.currentTarget).data("bs." + this.type, i)), e instanceof t.Event && (i.inState["focusout" == e.type ? "focus" : "hover"] = !1), i.isInStateTrue() ? void 0 : (clearTimeout(i.timeout), i.hoverState = "out", i.options.delay && i.options.delay.hide ? void(i.timeout = setTimeout(function () {
"out" == i.hoverState && i.hide()
}, i.options.delay.hide)) : i.hide())
}, i.prototype.show = function () {
var e = t.Event("show.bs." + this.type);
if (this.hasContent() && this.enabled) {
this.$element.trigger(e);
var o = t.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]);
if (e.isDefaultPrevented() || !o)return;
var n = this, s = this.tip(), a = this.getUID(this.type);
this.setContent(), s.attr("id", a), this.$element.attr("aria-describedby", a), this.options.animation && s.addClass("fade");
var r = "function" == typeof this.options.placement ? this.options.placement.call(this, s[0], this.$element[0]) : this.options.placement, l = /\s?auto?\s?/i, h = l.test(r);
h && (r = r.replace(l, "") || "top"), s.detach().css({
top: 0,
left: 0,
display: "block"
}).addClass(r).data("bs." + this.type, this), this.options.container ? s.appendTo(this.options.container) : s.insertAfter(this.$element), this.$element.trigger("inserted.bs." + this.type);
var d = this.getPosition(), p = s[0].offsetWidth, c = s[0].offsetHeight;
if (h) {
var f = r, u = this.getPosition(this.$viewport);
r = "bottom" == r && d.bottom + c > u.bottom ? "top" : "top" == r && d.top - c < u.top ? "bottom" : "right" == r && d.right + p > u.width ? "left" : "left" == r && d.left - p < u.left ? "right" : r, s.removeClass(f).addClass(r)
}
var g = this.getCalculatedOffset(r, d, p, c);
this.applyPlacement(g, r);
var m = function () {
var t = n.hoverState;
n.$element.trigger("shown.bs." + n.type), n.hoverState = null, "out" == t && n.leave(n)
};
t.support.transition && this.$tip.hasClass("fade") ? s.one("bsTransitionEnd", m).emulateTransitionEnd(i.TRANSITION_DURATION) : m()
}
}, i.prototype.applyPlacement = function (e, i) {
var o = this.tip(), n = o[0].offsetWidth, s = o[0].offsetHeight, a = parseInt(o.css("margin-top"), 10), r = parseInt(o.css("margin-left"), 10);
isNaN(a) && (a = 0), isNaN(r) && (r = 0), e.top += a, e.left += r, t.offset.setOffset(o[0], t.extend({
using: function (t) {
o.css({top: Math.round(t.top), left: Math.round(t.left)})
}
}, e), 0), o.addClass("in");
var l = o[0].offsetWidth, h = o[0].offsetHeight;
"top" == i && h != s && (e.top = e.top + s - h);
var d = this.getViewportAdjustedDelta(i, e, l, h);
d.left ? e.left += d.left : e.top += d.top;
var p = /top|bottom/.test(i), c = p ? 2 * d.left - n + l : 2 * d.top - s + h, f = p ? "offsetWidth" : "offsetHeight";
o.offset(e), this.replaceArrow(c, o[0][f], p)
}, i.prototype.replaceArrow = function (t, e, i) {
this.arrow().css(i ? "left" : "top", 50 * (1 - t / e) + "%").css(i ? "top" : "left", "")
}, i.prototype.setContent = function () {
var t = this.tip(), e = this.getTitle();
t.find(".tooltip-inner")[this.options.html ? "html" : "text"](e), t.removeClass("fade in top bottom left right")
}, i.prototype.hide = function (e) {
function o() {
"in" != n.hoverState && s.detach(), n.$element.removeAttr("aria-describedby").trigger("hidden.bs." + n.type), e && e()
}
var n = this, s = t(this.$tip), a = t.Event("hide.bs." + this.type);
return this.$element.trigger(a), a.isDefaultPrevented() ? void 0 : (s.removeClass("in"), t.support.transition && s.hasClass("fade") ? s.one("bsTransitionEnd", o).emulateTransitionEnd(i.TRANSITION_DURATION) : o(), this.hoverState = null, this)
}, i.prototype.fixTitle = function () {
var t = this.$element;
(t.attr("title") || "string" != typeof t.attr("data-original-title")) && t.attr("data-original-title", t.attr("title") || "").attr("title", "")
}, i.prototype.hasContent = function () {
return this.getTitle()
}, i.prototype.getPosition = function (e) {
e = e || this.$element;
var i = e[0], o = "BODY" == i.tagName, n = i.getBoundingClientRect();
null == n.width && (n = t.extend({}, n, {width: n.right - n.left, height: n.bottom - n.top}));
var s = o ? {
top: 0,
left: 0
} : e.offset(), a = {scroll: o ? document.documentElement.scrollTop || document.body.scrollTop : e.scrollTop()}, r = o ? {
width: t(window).width(),
height: t(window).height()
} : null;
return t.extend({}, n, a, r, s)
}, i.prototype.getCalculatedOffset = function (t, e, i, o) {
return "bottom" == t ? {
top: e.top + e.height,
left: e.left + e.width / 2 - i / 2
} : "top" == t ? {
top: e.top - o,
left: e.left + e.width / 2 - i / 2
} : "left" == t ? {top: e.top + e.height / 2 - o / 2, left: e.left - i} : {
top: e.top + e.height / 2 - o / 2,
left: e.left + e.width
}
}, i.prototype.getViewportAdjustedDelta = function (t, e, i, o) {
var n = {top: 0, left: 0};
if (!this.$viewport)return n;
var s = this.options.viewport && this.options.viewport.padding || 0, a = this.getPosition(this.$viewport);
if (/right|left/.test(t)) {
var r = e.top - s - a.scroll, l = e.top + s - a.scroll + o;
r < a.top ? n.top = a.top - r : l > a.top + a.height && (n.top = a.top + a.height - l)
} else {
var h = e.left - s, d = e.left + s + i;
h < a.left ? n.left = a.left - h : d > a.right && (n.left = a.left + a.width - d)
}
return n
}, i.prototype.getTitle = function () {
var t, e = this.$element, i = this.options;
return t = e.attr("data-original-title") || ("function" == typeof i.title ? i.title.call(e[0]) : i.title)
}, i.prototype.getUID = function (t) {
do t += ~~(1e6 * Math.random()); while (document.getElementById(t));
return t
}, i.prototype.tip = function () {
if (!this.$tip && (this.$tip = t(this.options.template), 1 != this.$tip.length))throw new Error(this.type + " `template` option must consist of exactly 1 top-level element!");
return this.$tip
}, i.prototype.arrow = function () {
return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow")
}, i.prototype.enable = function () {
this.enabled = !0
}, i.prototype.disable = function () {
this.enabled = !1
}, i.prototype.toggleEnabled = function () {
this.enabled = !this.enabled
}, i.prototype.toggle = function (e) {
var i = this;
e && (i = t(e.currentTarget).data("bs." + this.type), i || (i = new this.constructor(e.currentTarget, this.getDelegateOptions()), t(e.currentTarget).data("bs." + this.type, i))), e ? (i.inState.click = !i.inState.click, i.isInStateTrue() ? i.enter(i) : i.leave(i)) : i.tip().hasClass("in") ? i.leave(i) : i.enter(i)
}, i.prototype.destroy = function () {
var t = this;
clearTimeout(this.timeout), this.hide(function () {
t.$element.off("." + t.type).removeData("bs." + t.type), t.$tip && t.$tip.detach(), t.$tip = null, t.$arrow = null, t.$viewport = null
})
};
var o = t.fn.tooltip;
t.fn.tooltip = e, t.fn.tooltip.Constructor = i, t.fn.tooltip.noConflict = function () {
return t.fn.tooltip = o, this
}
}(jQuery), +function (t) {
"use strict";
function e(e) {
return this.each(function () {
var o = t(this), n = o.data("bs.popover"), s = "object" == typeof e && e;
(n || !/destroy|hide/.test(e)) && (n || o.data("bs.popover", n = new i(this, s)), "string" == typeof e && n[e]())
})
}
var i = function (t, e) {
this.init("popover", t, e)
};
if (!t.fn.tooltip)throw new Error("Popover requires tooltip.js");
i.VERSION = "3.3.5", i.DEFAULTS = t.extend({}, t.fn.tooltip.Constructor.DEFAULTS, {
placement: "right",
trigger: "click",
content: "",
template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
}), i.prototype = t.extend({}, t.fn.tooltip.Constructor.prototype), i.prototype.constructor = i, i.prototype.getDefaults = function () {
return i.DEFAULTS
}, i.prototype.setContent = function () {
var t = this.tip(), e = this.getTitle(), i = this.getContent();
t.find(".popover-title")[this.options.html ? "html" : "text"](e), t.find(".popover-content").children().detach().end()[this.options.html ? "string" == typeof i ? "html" : "append" : "text"](i), t.removeClass("fade top bottom left right in"), t.find(".popover-title").html() || t.find(".popover-title").hide()
}, i.prototype.hasContent = function () {
return this.getTitle() || this.getContent()
}, i.prototype.getContent = function () {
var t = this.$element, e = this.options;
return t.attr("data-content") || ("function" == typeof e.content ? e.content.call(t[0]) : e.content)
}, i.prototype.arrow = function () {
return this.$arrow = this.$arrow || this.tip().find(".arrow")
};
var o = t.fn.popover;
t.fn.popover = e, t.fn.popover.Constructor = i, t.fn.popover.noConflict = function () {
return t.fn.popover = o, this
}
}(jQuery), +function (t) {
"use strict";
function e(e) {
return this.each(function () {
var o = t(this), n = o.data("bs.tab");
n || o.data("bs.tab", n = new i(this)), "string" == typeof e && n[e]()
})
}
var i = function (e) {
this.element = t(e)
};
i.VERSION = "3.3.5", i.TRANSITION_DURATION = 150, i.prototype.show = function () {
var e = this.element, i = e.closest("ul:not(.dropdown-menu)"), o = e.data("target");
if (o || (o = e.attr("href"), o = o && o.replace(/.*(?=#[^\s]*$)/, "")), !e.parent("li").hasClass("active")) {
var n = i.find(".active:last a"), s = t.Event("hide.bs.tab", {relatedTarget: e[0]}), a = t.Event("show.bs.tab", {relatedTarget: n[0]});
if (n.trigger(s), e.trigger(a), !a.isDefaultPrevented() && !s.isDefaultPrevented()) {
var r = t(o);
this.activate(e.closest("li"), i), this.activate(r, r.parent(), function () {
n.trigger({type: "hidden.bs.tab", relatedTarget: e[0]}), e.trigger({
type: "shown.bs.tab",
relatedTarget: n[0]
})
})
}
}
}, i.prototype.activate = function (e, o, n) {
function s() {
a.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded", !1), e.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded", !0), r ? (e[0].offsetWidth, e.addClass("in")) : e.removeClass("fade"), e.parent(".dropdown-menu").length && e.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded", !0), n && n()
}
var a = o.find("> .active"), r = n && t.support.transition && (a.length && a.hasClass("fade") || !!o.find("> .fade").length);
a.length && r ? a.one("bsTransitionEnd", s).emulateTransitionEnd(i.TRANSITION_DURATION) : s(), a.removeClass("in")
};
var o = t.fn.tab;
t.fn.tab = e, t.fn.tab.Constructor = i, t.fn.tab.noConflict = function () {
return t.fn.tab = o, this
};
var n = function (i) {
i.preventDefault(), e.call(t(this), "show")
};
t(document).on("click.bs.tab.data-api", '[data-toggle="tab"]', n).on("click.bs.tab.data-api", '[data-toggle="pill"]', n)
}(jQuery), +function (t) {
"use strict";
function e(e) {
return this.each(function () {
var o = t(this), n = o.data("bs.affix"), s = "object" == typeof e && e;
n || o.data("bs.affix", n = new i(this, s)), "string" == typeof e && n[e]()
})
}
var i = function (e, o) {
this.options = t.extend({}, i.DEFAULTS, o), this.$target = t(this.options.target).on("scroll.bs.affix.data-api", t.proxy(this.checkPosition, this)).on("click.bs.affix.data-api", t.proxy(this.checkPositionWithEventLoop, this)), this.$element = t(e), this.affixed = null, this.unpin = null, this.pinnedOffset = null, this.checkPosition()
};
i.VERSION = "3.3.5", i.RESET = "affix affix-top affix-bottom", i.DEFAULTS = {
offset: 0,
target: window
}, i.prototype.getState = function (t, e, i, o) {
var n = this.$target.scrollTop(), s = this.$element.offset(), a = this.$target.height();
if (null != i && "top" == this.affixed)return i > n ? "top" : !1;
if ("bottom" == this.affixed)return null != i ? n + this.unpin <= s.top ? !1 : "bottom" : t - o >= n + a ? !1 : "bottom";
var r = null == this.affixed, l = r ? n : s.top, h = r ? a : e;
return null != i && i >= n ? "top" : null != o && l + h >= t - o ? "bottom" : !1
}, i.prototype.getPinnedOffset = function () {
if (this.pinnedOffset)return this.pinnedOffset;
this.$element.removeClass(i.RESET).addClass("affix");
var t = this.$target.scrollTop(), e = this.$element.offset();
return this.pinnedOffset = e.top - t
}, i.prototype.checkPositionWithEventLoop = function () {
setTimeout(t.proxy(this.checkPosition, this), 1)
}, i.prototype.checkPosition = function () {
if (this.$element.is(":visible")) {
var e = this.$element.height(), o = this.options.offset, n = o.top, s = o.bottom, a = Math.max(t(document).height(), t(document.body).height());
"object" != typeof o && (s = n = o), "function" == typeof n && (n = o.top(this.$element)), "function" == typeof s && (s = o.bottom(this.$element));
var r = this.getState(a, e, n, s);
if (this.affixed != r) {
null != this.unpin && this.$element.css("top", "");
var l = "affix" + (r ? "-" + r : ""), h = t.Event(l + ".bs.affix");
if (this.$element.trigger(h), h.isDefaultPrevented())return;
this.affixed = r, this.unpin = "bottom" == r ? this.getPinnedOffset() : null, this.$element.removeClass(i.RESET).addClass(l).trigger(l.replace("affix", "affixed") + ".bs.affix")
}
"bottom" == r && this.$element.offset({top: a - e - s})
}
};
var o = t.fn.affix;
t.fn.affix = e, t.fn.affix.Constructor = i, t.fn.affix.noConflict = function () {
return t.fn.affix = o, this
}, t(window).on("load", function () {
t('[data-spy="affix"]').each(function () {
var i = t(this), o = i.data();
o.offset = o.offset || {}, null != o.offsetBottom && (o.offset.bottom = o.offsetBottom), null != o.offsetTop && (o.offset.top = o.offsetTop), e.call(i, o)
})
})
}(jQuery), +function (t) {
"use strict";
function e(e) {
var i, o = e.attr("data-target") || (i = e.attr("href")) && i.replace(/.*(?=#[^\s]+$)/, "");
return t(o)
}
function i(e) {
return this.each(function () {
var i = t(this), n = i.data("bs.collapse"), s = t.extend({}, o.DEFAULTS, i.data(), "object" == typeof e && e);
!n && s.toggle && /show|hide/.test(e) && (s.toggle = !1), n || i.data("bs.collapse", n = new o(this, s)), "string" == typeof e && n[e]()
})
}
var o = function (e, i) {
this.$element = t(e), this.options = t.extend({}, o.DEFAULTS, i), this.$trigger = t('[data-toggle="collapse"][href="#' + e.id + '"],[data-toggle="collapse"][data-target="#' + e.id + '"]'), this.transitioning = null, this.options.parent ? this.$parent = this.getParent() : this.addAriaAndCollapsedClass(this.$element, this.$trigger), this.options.toggle && this.toggle()
};
o.VERSION = "3.3.5", o.TRANSITION_DURATION = 350, o.DEFAULTS = {toggle: !0}, o.prototype.dimension = function () {
var t = this.$element.hasClass("width");
return t ? "width" : "height"
}, o.prototype.show = function () {
if (!this.transitioning && !this.$element.hasClass("in")) {
var e, n = this.$parent && this.$parent.children(".panel").children(".in, .collapsing");
if (!(n && n.length && (e = n.data("bs.collapse"), e && e.transitioning))) {
var s = t.Event("show.bs.collapse");
if (this.$element.trigger(s), !s.isDefaultPrevented()) {
n && n.length && (i.call(n, "hide"), e || n.data("bs.collapse", null));
var a = this.dimension();
this.$element.removeClass("collapse").addClass("collapsing")[a](0).attr("aria-expanded", !0), this.$trigger.removeClass("collapsed").attr("aria-expanded", !0), this.transitioning = 1;
var r = function () {
this.$element.removeClass("collapsing").addClass("collapse in")[a](""), this.transitioning = 0, this.$element.trigger("shown.bs.collapse")
};
if (!t.support.transition)return r.call(this);
var l = t.camelCase(["scroll", a].join("-"));
this.$element.one("bsTransitionEnd", t.proxy(r, this)).emulateTransitionEnd(o.TRANSITION_DURATION)[a](this.$element[0][l]);
}
}
}
}, o.prototype.hide = function () {
if (!this.transitioning && this.$element.hasClass("in")) {
var e = t.Event("hide.bs.collapse");
if (this.$element.trigger(e), !e.isDefaultPrevented()) {
var i = this.dimension();
this.$element[i](this.$element[i]())[0].offsetHeight, this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded", !1), this.$trigger.addClass("collapsed").attr("aria-expanded", !1), this.transitioning = 1;
var n = function () {
this.transitioning = 0, this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")
};
return t.support.transition ? void this.$element[i](0).one("bsTransitionEnd", t.proxy(n, this)).emulateTransitionEnd(o.TRANSITION_DURATION) : n.call(this)
}
}
}, o.prototype.toggle = function () {
this[this.$element.hasClass("in") ? "hide" : "show"]()
}, o.prototype.getParent = function () {
return t(this.options.parent).find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]').each(t.proxy(function (i, o) {
var n = t(o);
this.addAriaAndCollapsedClass(e(n), n)
}, this)).end()
}, o.prototype.addAriaAndCollapsedClass = function (t, e) {
var i = t.hasClass("in");
t.attr("aria-expanded", i), e.toggleClass("collapsed", !i).attr("aria-expanded", i)
};
var n = t.fn.collapse;
t.fn.collapse = i, t.fn.collapse.Constructor = o, t.fn.collapse.noConflict = function () {
return t.fn.collapse = n, this
}, t(document).on("click.bs.collapse.data-api", '[data-toggle="collapse"]', function (o) {
var n = t(this);
n.attr("data-target") || o.preventDefault();
var s = e(n), a = s.data("bs.collapse"), r = a ? "toggle" : n.data();
i.call(s, r)
})
}(jQuery), +function (t) {
"use strict";
function e(i, o) {
this.$body = t(document.body), this.$scrollElement = t(t(i).is(document.body) ? window : i), this.options = t.extend({}, e.DEFAULTS, o), this.selector = (this.options.target || "") + " .nav li > a", this.offsets = [], this.targets = [], this.activeTarget = null, this.scrollHeight = 0, this.$scrollElement.on("scroll.bs.scrollspy", t.proxy(this.process, this)), this.refresh(), this.process()
}
function i(i) {
return this.each(function () {
var o = t(this), n = o.data("bs.scrollspy"), s = "object" == typeof i && i;
n || o.data("bs.scrollspy", n = new e(this, s)), "string" == typeof i && n[i]()
})
}
e.VERSION = "3.3.5", e.DEFAULTS = {offset: 10}, e.prototype.getScrollHeight = function () {
return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
}, e.prototype.refresh = function () {
var e = this, i = "offset", o = 0;
this.offsets = [], this.targets = [], this.scrollHeight = this.getScrollHeight(), t.isWindow(this.$scrollElement[0]) || (i = "position", o = this.$scrollElement.scrollTop()), this.$body.find(this.selector).map(function () {
var e = t(this), n = e.data("target") || e.attr("href"), s = /^#./.test(n) && t(n);
return s && s.length && s.is(":visible") && [[s[i]().top + o, n]] || null
}).sort(function (t, e) {
return t[0] - e[0]
}).each(function () {
e.offsets.push(this[0]), e.targets.push(this[1])
})
}, e.prototype.process = function () {
var t, e = this.$scrollElement.scrollTop() + this.options.offset, i = this.getScrollHeight(), o = this.options.offset + i - this.$scrollElement.height(), n = this.offsets, s = this.targets, a = this.activeTarget;
if (this.scrollHeight != i && this.refresh(), e >= o)return a != (t = s[s.length - 1]) && this.activate(t);
if (a && e < n[0])return this.activeTarget = null, this.clear();
for (t = n.length; t--;)a != s[t] && e >= n[t] && (void 0 === n[t + 1] || e < n[t + 1]) && this.activate(s[t])
}, e.prototype.activate = function (e) {
this.activeTarget = e, this.clear();
var i = this.selector + '[data-target="' + e + '"],' + this.selector + '[href="' + e + '"]', o = t(i).parents("li").addClass("active");
o.parent(".dropdown-menu").length && (o = o.closest("li.dropdown").addClass("active")), o.trigger("activate.bs.scrollspy")
}, e.prototype.clear = function () {
t(this.selector).parentsUntil(this.options.target, ".active").removeClass("active")
};
var o = t.fn.scrollspy;
t.fn.scrollspy = i, t.fn.scrollspy.Constructor = e, t.fn.scrollspy.noConflict = function () {
return t.fn.scrollspy = o, this
}, t(window).on("load.bs.scrollspy.data-api", function () {
t('[data-spy="scroll"]').each(function () {
var e = t(this);
i.call(e, e.data())
})
})
}(jQuery), +function (t) {
"use strict";
function e() {
var t = document.createElement("bootstrap"), e = {
WebkitTransition: "webkitTransitionEnd",
MozTransition: "transitionend",
OTransition: "oTransitionEnd otransitionend",
transition: "transitionend"
};
for (var i in e)if (void 0 !== t.style[i])return {end: e[i]};
return !1
}
t.fn.emulateTransitionEnd = function (e) {
var i = !1, o = this;
t(this).one("bsTransitionEnd", function () {
i = !0
});
var n = function () {
i || t(o).trigger(t.support.transition.end)
};
return setTimeout(n, e), this
}, t(function () {
t.support.transition = e(), t.support.transition && (t.event.special.bsTransitionEnd = {
bindType: t.support.transition.end,
delegateType: t.support.transition.end,
handle: function (e) {
return t(e.target).is(this) ? e.handleObj.handler.apply(this, arguments) : void 0
}
})
})
}(jQuery);
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
<div class="container-fluid"> <div class="container-fluid">
<div class="app" ng-controller="AppPageController"> <div class="app" ng-controller="AppPageController">
<ol class="breadcrumb"> <ol class="breadcrumb">
<li >{{breadcrumb.project}}</li> <li>{{breadcrumb.project}}</li>
<li>{{breadcrumb.nav}}</li> <li>{{breadcrumb.nav}}</li>
<li ng-show="breadcrumb.env">{{breadcrumb.env}}</li> <li ng-show="breadcrumb.env">{{breadcrumb.env}}</li>
<!--<li>1.0</li>--> <!--<li>1.0</li>-->
......
<div class="footer"> <div class="footer">
<p class="text-center"> <p class="text-center">
<span class="glyphicon glyphicon-copyright-mark" aria-hidden="true"></span>携程 框架研发部<br> <span class="glyphicon glyphicon-copyright-mark" aria-hidden="true"></span>携程 框架研发部<br>
......
...@@ -29,7 +29,8 @@ ...@@ -29,7 +29,8 @@
<div class="form-group"> <div class="form-group">
<label class="col-sm-2 control-label"><font style="color: red">*</font> 应用ID</label> <label class="col-sm-2 control-label"><font style="color: red">*</font> 应用ID</label>
<div class="col-sm-3"> <div class="col-sm-3">
<input type="text" class="form-control" name="appAppId" ng-model="app.appId" required> <input type="text" class="form-control" name="appAppId" ng-model="app.appId"
required>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
...@@ -48,7 +49,8 @@ ...@@ -48,7 +49,8 @@
<div class="form-group"> <div class="form-group">
<label class="col-sm-2 control-label">手机号</label> <label class="col-sm-2 control-label">手机号</label>
<div class="col-sm-3"> <div class="col-sm-3">
<input type="text" class="form-control" name="appOwnerPhone" ng-model="app.ownerPhone"> <input type="text" class="form-control" name="appOwnerPhone"
ng-model="app.ownerPhone">
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
......
package com.ctrip.apollo.portal; package com.ctrip.apollo.portal;
import com.ctrip.apollo.portal.controller.AppControllerTest;
import com.ctrip.apollo.portal.repository.AppRepositoryTest;
import com.ctrip.apollo.portal.service.ConfigServiceTest; import com.ctrip.apollo.portal.service.ConfigServiceTest;
import com.ctrip.apollo.portal.service.PrivilegeServiceTest;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.Suite; import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses; import org.junit.runners.Suite.SuiteClasses;
import com.ctrip.apollo.portal.controller.AppControllerTest;
import com.ctrip.apollo.portal.repository.AppRepositoryTest;
import com.ctrip.apollo.portal.service.PrivilegeServiceTest;
@RunWith(Suite.class) @RunWith(Suite.class)
@SuiteClasses({AppControllerTest.class, AppRepositoryTest.class, PrivilegeServiceTest.class, ConfigServiceTest.class @SuiteClasses({AppControllerTest.class, AppRepositoryTest.class, PrivilegeServiceTest.class,
ConfigServiceTest.class
}) })
public class AllTests { public class AllTests {
......
package com.ctrip.apollo.portal.controller; package com.ctrip.apollo.portal.controller;
import java.net.URI; import com.ctrip.apollo.portal.AbstractPortalTest;
import java.net.URISyntaxException; import com.ctrip.apollo.portal.entity.App;
import com.ctrip.apollo.portal.repository.AppRepository;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
...@@ -13,9 +14,8 @@ import org.springframework.http.HttpStatus; ...@@ -13,9 +14,8 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import com.ctrip.apollo.portal.AbstractPortalTest; import java.net.URI;
import com.ctrip.apollo.portal.entity.App; import java.net.URISyntaxException;
import com.ctrip.apollo.portal.repository.AppRepository;
@WebIntegrationTest @WebIntegrationTest
......
package com.ctrip.apollo.portal.repository; package com.ctrip.apollo.portal.repository;
import com.ctrip.apollo.portal.AbstractPortalTest;
import com.ctrip.apollo.portal.entity.App;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import com.ctrip.apollo.portal.AbstractPortalTest;
import com.ctrip.apollo.portal.entity.App;
public class AppRepositoryTest extends AbstractPortalTest{ public class AppRepositoryTest extends AbstractPortalTest {
@Autowired @Autowired
AppRepository repository; AppRepository repository;
......
package com.ctrip.apollo.portal.service; package com.ctrip.apollo.portal.service;
import com.ctrip.apollo.core.dto.*; import com.ctrip.apollo.core.dto.ClusterDTO;
import com.ctrip.apollo.core.dto.ConfigItemDTO;
import com.ctrip.apollo.core.dto.ReleaseSnapshotDTO;
import com.ctrip.apollo.core.dto.VersionDTO;
import com.ctrip.apollo.portal.RestUtils; import com.ctrip.apollo.portal.RestUtils;
import com.ctrip.apollo.portal.constants.PortalConstants; import com.ctrip.apollo.portal.constants.PortalConstants;
import com.ctrip.apollo.portal.entity.AppConfigVO; import com.ctrip.apollo.portal.entity.AppConfigVO;
import com.ctrip.apollo.portal.service.impl.ConfigServiceImpl; import com.ctrip.apollo.portal.service.impl.ConfigServiceImpl;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
...@@ -18,7 +22,8 @@ import org.springframework.test.util.ReflectionTestUtils; ...@@ -18,7 +22,8 @@ import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.*; import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
...@@ -76,7 +81,8 @@ public class ConfigServiceTest { ...@@ -76,7 +81,8 @@ public class ConfigServiceTest {
VersionDTO someVersion = assembleVersion(appId, "1.0", releaseId); VersionDTO someVersion = assembleVersion(appId, "1.0", releaseId);
ReleaseSnapshotDTO[] releaseSnapShots = new ReleaseSnapshotDTO[1]; ReleaseSnapshotDTO[] releaseSnapShots = new ReleaseSnapshotDTO[1];
releaseSnapShots[0] = releaseSnapShots[0] =
assembleReleaseSnapShot(11111, "default-cluster-name", "{\"6666.foo\":\"demo1\", \"6666.bar\":\"demo2\"}"); assembleReleaseSnapShot(11111, "default-cluster-name",
"{\"6666.foo\":\"demo1\", \"6666.bar\":\"demo2\"}");
restInvoke(ConfigServiceImpl.ADMIN_SERVICE_HOST + "/configs/release/" restInvoke(ConfigServiceImpl.ADMIN_SERVICE_HOST + "/configs/release/"
+ releaseId, ReleaseSnapshotDTO[].class, releaseSnapShots, releaseSnapShotResponse); + releaseId, ReleaseSnapshotDTO[].class, releaseSnapShots, releaseSnapShotResponse);
...@@ -101,7 +107,8 @@ public class ConfigServiceTest { ...@@ -101,7 +107,8 @@ public class ConfigServiceTest {
VersionDTO someVersion = assembleVersion(appId, "1.0", releaseId); VersionDTO someVersion = assembleVersion(appId, "1.0", releaseId);
ReleaseSnapshotDTO[] releaseSnapShots = new ReleaseSnapshotDTO[1]; ReleaseSnapshotDTO[] releaseSnapShots = new ReleaseSnapshotDTO[1];
releaseSnapShots[0] = releaseSnapShots[0] =
assembleReleaseSnapShot(11111, "default-cluster-name", "{\"6666.foo\":\"demo1\", \"6666.bar\":\"demo2\", \"5555.bar\":\"demo2\", \"22.bar\":\"demo2\"}"); assembleReleaseSnapShot(11111, "default-cluster-name",
"{\"6666.foo\":\"demo1\", \"6666.bar\":\"demo2\", \"5555.bar\":\"demo2\", \"22.bar\":\"demo2\"}");
restInvoke(ConfigServiceImpl.ADMIN_SERVICE_HOST + "/configs/release/" restInvoke(ConfigServiceImpl.ADMIN_SERVICE_HOST + "/configs/release/"
+ releaseId, ReleaseSnapshotDTO[].class, releaseSnapShots, releaseSnapShotResponse); + releaseId, ReleaseSnapshotDTO[].class, releaseSnapShots, releaseSnapShotResponse);
...@@ -109,10 +116,8 @@ public class ConfigServiceTest { ...@@ -109,10 +116,8 @@ public class ConfigServiceTest {
restInvoke(ConfigServiceImpl.ADMIN_SERVICE_HOST + "/version/" restInvoke(ConfigServiceImpl.ADMIN_SERVICE_HOST + "/version/"
+ versionId, VersionDTO.class, someVersion, versionResponse); + versionId, VersionDTO.class, someVersion, versionResponse);
AppConfigVO appConfigVO = configService.loadReleaseConfig(appId, versionId); AppConfigVO appConfigVO = configService.loadReleaseConfig(appId, versionId);
assertEquals(appConfigVO.getAppId(), appId); assertEquals(appConfigVO.getAppId(), appId);
assertEquals(appConfigVO.getVersionId(), versionId); assertEquals(appConfigVO.getVersionId(), versionId);
assertEquals(appConfigVO.getDefaultClusterConfigs().size(), 2); assertEquals(appConfigVO.getDefaultClusterConfigs().size(), 2);
...@@ -128,9 +133,11 @@ public class ConfigServiceTest { ...@@ -128,9 +133,11 @@ public class ConfigServiceTest {
VersionDTO someVersion = assembleVersion(appId, "1.0", releaseId); VersionDTO someVersion = assembleVersion(appId, "1.0", releaseId);
ReleaseSnapshotDTO[] releaseSnapShots = new ReleaseSnapshotDTO[2]; ReleaseSnapshotDTO[] releaseSnapShots = new ReleaseSnapshotDTO[2];
releaseSnapShots[0] = releaseSnapShots[0] =
assembleReleaseSnapShot(11111, "default-cluster-name", "{\"6666.foo\":\"demo1\", \"6666.bar\":\"demo2\"}"); assembleReleaseSnapShot(11111, "default-cluster-name",
"{\"6666.foo\":\"demo1\", \"6666.bar\":\"demo2\"}");
releaseSnapShots[1] = releaseSnapShots[1] =
assembleReleaseSnapShot(11112, "cluster1", "{\"6666.foo\":\"demo1\", \"6666.bar\":\"demo2\"}"); assembleReleaseSnapShot(11112, "cluster1",
"{\"6666.foo\":\"demo1\", \"6666.bar\":\"demo2\"}");
restInvoke(ConfigServiceImpl.ADMIN_SERVICE_HOST + "/configs/release/" restInvoke(ConfigServiceImpl.ADMIN_SERVICE_HOST + "/configs/release/"
+ releaseId, ReleaseSnapshotDTO[].class, releaseSnapShots, releaseSnapShotResponse); + releaseId, ReleaseSnapshotDTO[].class, releaseSnapShots, releaseSnapShotResponse);
...@@ -157,7 +164,8 @@ public class ConfigServiceTest { ...@@ -157,7 +164,8 @@ public class ConfigServiceTest {
+ appId, ClusterDTO[].class, someClusters, clusterResponse); + appId, ClusterDTO[].class, someClusters, clusterResponse);
restInvoke(ConfigServiceImpl.ADMIN_SERVICE_HOST restInvoke(ConfigServiceImpl.ADMIN_SERVICE_HOST
+ "/configs/latest?clusterIds=100,101", ConfigItemDTO[].class, someConfigItem, configItemResponse); + "/configs/latest?clusterIds=100,101", ConfigItemDTO[].class, someConfigItem,
configItemResponse);
AppConfigVO appConfigVO = configService.loadLatestConfig(appId); AppConfigVO appConfigVO = configService.loadLatestConfig(appId);
...@@ -168,8 +176,11 @@ public class ConfigServiceTest { ...@@ -168,8 +176,11 @@ public class ConfigServiceTest {
assertEquals(appConfigVO.getOverrideClusterConfigs().size(), 1); assertEquals(appConfigVO.getOverrideClusterConfigs().size(), 1);
} }
private <T> void restInvoke(String url, Class<T> responseType, T result, ResponseEntity someResponse) { private <T> void restInvoke(String url, Class<T> responseType, T result,
when(restTemplate.exchange(eq(url), eq(HttpMethod.GET), any(HttpEntity.class), eq(responseType))).thenReturn(someResponse); ResponseEntity someResponse) {
when(
restTemplate.exchange(eq(url), eq(HttpMethod.GET), any(HttpEntity.class), eq(responseType)))
.thenReturn(someResponse);
when(someResponse.getStatusCode()).thenReturn(HttpStatus.OK); when(someResponse.getStatusCode()).thenReturn(HttpStatus.OK);
when(someResponse.getBody()).thenReturn(result); when(someResponse.getBody()).thenReturn(result);
} }
...@@ -185,7 +196,8 @@ public class ConfigServiceTest { ...@@ -185,7 +196,8 @@ public class ConfigServiceTest {
private ReleaseSnapshotDTO[] assembleReleaseSnapShots() { private ReleaseSnapshotDTO[] assembleReleaseSnapShots() {
ReleaseSnapshotDTO[] releaseSnapShots = new ReleaseSnapshotDTO[3]; ReleaseSnapshotDTO[] releaseSnapShots = new ReleaseSnapshotDTO[3];
releaseSnapShots[0] = releaseSnapShots[0] =
assembleReleaseSnapShot(11111, "default-cluster-name", "{\"6666.foo\":\"demo1\", \"6666.bar\":\"demo2\",\"3333.foo\":\"1008\",\"4444.bar\":\"99901\"}"); assembleReleaseSnapShot(11111, "default-cluster-name",
"{\"6666.foo\":\"demo1\", \"6666.bar\":\"demo2\",\"3333.foo\":\"1008\",\"4444.bar\":\"99901\"}");
releaseSnapShots[1] = releaseSnapShots[1] =
assembleReleaseSnapShot(11111, "cluster1", "{\"6666.foo\":\"demo1\"}"); assembleReleaseSnapShot(11111, "cluster1", "{\"6666.foo\":\"demo1\"}");
releaseSnapShots[2] = releaseSnapShots[2] =
...@@ -193,7 +205,8 @@ public class ConfigServiceTest { ...@@ -193,7 +205,8 @@ public class ConfigServiceTest {
return releaseSnapShots; return releaseSnapShots;
} }
private ReleaseSnapshotDTO assembleReleaseSnapShot(long releaseId, String clusterName, String configurations) { private ReleaseSnapshotDTO assembleReleaseSnapShot(long releaseId, String clusterName,
String configurations) {
ReleaseSnapshotDTO releaseSnapShot = new ReleaseSnapshotDTO(); ReleaseSnapshotDTO releaseSnapShot = new ReleaseSnapshotDTO();
releaseSnapShot.setReleaseId(releaseId); releaseSnapShot.setReleaseId(releaseId);
releaseSnapShot.setClusterName(clusterName); releaseSnapShot.setClusterName(clusterName);
...@@ -230,7 +243,8 @@ public class ConfigServiceTest { ...@@ -230,7 +243,8 @@ public class ConfigServiceTest {
return configItems; return configItems;
} }
private ConfigItemDTO assembleConfigItem(long clusterId, String clusterName, int appId, String key, String value) { private ConfigItemDTO assembleConfigItem(long clusterId, String clusterName, int appId,
String key, String value) {
ConfigItemDTO configItem = new ConfigItemDTO(); ConfigItemDTO configItem = new ConfigItemDTO();
configItem.setClusterName(clusterName); configItem.setClusterName(clusterName);
configItem.setClusterId(clusterId); configItem.setClusterId(clusterId);
......
package com.ctrip.apollo.portal.service; package com.ctrip.apollo.portal.service;
import java.util.List; import com.ctrip.apollo.portal.AbstractPortalTest;
import com.ctrip.apollo.portal.entity.App;
import com.ctrip.apollo.portal.entity.Privilege;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import com.ctrip.apollo.portal.AbstractPortalTest; import java.util.List;
import com.ctrip.apollo.portal.entity.App;
import com.ctrip.apollo.portal.entity.Privilege;
public class PrivilegeServiceTest extends AbstractPortalTest { public class PrivilegeServiceTest extends AbstractPortalTest {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment