├── .gitignore ├── README.md ├── config.properties ├── pom.xml ├── scripts └── update-production.sh └── src └── main ├── java └── com │ └── mlesniak │ └── sap │ └── playground │ ├── EnvironmentContextInitializer.java │ ├── Main.java │ ├── MainController.java │ ├── TextEntry.java │ ├── TextRepository.java │ ├── TextService.java │ └── VersionController.java ├── resources ├── application-production.properties ├── application.properties ├── logback.xml └── public │ ├── css │ └── main.css │ ├── i18n │ ├── messages_de.json │ └── messages_en.json │ ├── index.html │ ├── js │ └── application.js │ └── swagger │ ├── css │ ├── print.css │ ├── reset.css │ ├── screen.css │ ├── style.css │ └── typography.css │ ├── fonts │ ├── DroidSans-Bold.ttf │ └── DroidSans.ttf │ ├── images │ ├── explorer_icons.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ ├── logo_small.png │ ├── pet_store_api.png │ ├── throbber.gif │ └── wordnik_api.png │ ├── index.html │ ├── lang │ ├── en.js │ ├── es.js │ ├── fr.js │ ├── it.js │ ├── ja.js │ ├── pt.js │ ├── ru.js │ ├── tr.js │ ├── translator.js │ └── zh-cn.js │ ├── lib │ ├── backbone-min.js │ ├── handlebars-2.0.0.js │ ├── highlight.7.3.pack.js │ ├── jquery-1.8.0.min.js │ ├── jquery.ba-bbq.min.js │ ├── jquery.slideto.min.js │ ├── jquery.wiggle.min.js │ ├── marked.js │ ├── swagger-oauth.js │ ├── underscore-min.js │ └── underscore-min.map │ ├── o2c.html │ ├── swagger-ui.js │ └── swagger-ui.min.js └── webapp └── WEB-INF └── web.xml /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### JetBrains template 3 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio 4 | 5 | *.iml 6 | 7 | ## Directory-based project format: 8 | .idea/ 9 | # if you remove the above rule, at least ignore the following: 10 | 11 | # User-specific stuff: 12 | # .idea/workspace.xml 13 | # .idea/tasks.xml 14 | # .idea/dictionaries 15 | 16 | # Sensitive or high-churn files: 17 | # .idea/dataSources.ids 18 | # .idea/dataSources.xml 19 | # .idea/sqlDataSources.xml 20 | # .idea/dynamic.xml 21 | # .idea/uiDesigner.xml 22 | 23 | # Gradle: 24 | # .idea/gradle.xml 25 | # .idea/libraries 26 | 27 | # Mongo Explorer plugin: 28 | # .idea/mongoSettings.xml 29 | 30 | ## File-based project format: 31 | *.ipr 32 | *.iws 33 | 34 | ## Plugin-specific files: 35 | 36 | # IntelliJ 37 | /out/ 38 | 39 | # mpeltonen/sbt-idea plugin 40 | .idea_modules/ 41 | 42 | # JIRA plugin 43 | atlassian-ide-plugin.xml 44 | 45 | # Crashlytics plugin (for Android Studio and IntelliJ) 46 | com_crashlytics_export_strings.xml 47 | crashlytics.properties 48 | crashlytics-build.properties 49 | ### Java template 50 | *.class 51 | 52 | # Mobile Tools for Java (J2ME) 53 | .mtj.tmp/ 54 | 55 | # Package Files # 56 | *.jar 57 | *.war 58 | *.ear 59 | 60 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 61 | hs_err_pid* 62 | 63 | target/ 64 | 65 | 66 | src/main/resources/git.properties 67 | derby.log 68 | /.settings/ 69 | /.classpath 70 | /.project 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | This is an example of a spring-boot application with JPA and Angular which works on SAP's HCP platform. If the 4 | server is running, you can find a demo [here](https://datalakep1941749386trial.hanatrial.ondemand.com/server/) 5 | 6 | ## Features: 7 | 8 | Backend: 9 | 10 | - Spring-Boot 11 | - Local embedded profile w/o external dependencies for fast development 12 | - Production profile with script-based hot-update functionality 13 | - JPA (w/ Hibernate) using HANA as the database 14 | - RESTful API 15 | - API documentation with swagger 16 | 17 | Frontend: 18 | 19 | - AngularJS and Bootstrap 20 | - I18N 21 | - Using ```$resource``` 22 | - Animations 23 | 24 | 25 | ## Initial deployment 26 | 27 | Build the deployable .war-file with 28 | 29 | mvn -P production clean package 30 | 31 | If you configure your server in the HCP frontend, do not forget to set 32 | 33 | -Dspring.profiles.active=production 34 | 35 | otherwise no database connection can be established. 36 | 37 | 38 | ## Local development 39 | 40 | Start local development by simply executing ```com.mlesniak.sap.playground.Main```. 41 | 42 | 43 | 44 | ## TODOs 45 | 46 | - Better documentation of initial and continous deployment; see scripts/update-production.sh for an example -------------------------------------------------------------------------------- /config.properties: -------------------------------------------------------------------------------- 1 | # Password not mentioned for obvious reasons. 2 | 3 | host=hanatrial.ondemand.com 4 | user=m.lesniak@micromata.de 5 | application=datalake 6 | source=target/server.war 7 | delta=true 8 | account=p1941749386trial 9 | strategy=restart-runtime -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.mlesniak.sap 8 | playground 9 | 1.0-SNAPSHOT 10 | war 11 | 12 | 13 | org.springframework.boot 14 | spring-boot-starter-parent 15 | 1.3.0.RELEASE 16 | 17 | 18 | 19 | 20 | 1.7 21 | UTF-8 22 | 23 | 24 | 7.0.59 25 | 26 | 27 | 28 | 29 | 30 | dev 31 | 32 | true 33 | 34 | 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter-web 39 | 40 | 41 | 42 | org.apache.derby 43 | derby 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | production 52 | 53 | false 54 | 55 | 56 | 57 | org.springframework.boot 58 | spring-boot-starter-web 59 | 60 | 61 | 62 | org.springframework.boot 63 | spring-boot-starter-tomcat 64 | 65 | 66 | org.apache.tomcat.embed 67 | tomcat-embed-el 68 | 69 | 70 | logback-classic 71 | ch.qos.logback 72 | 73 | 74 | 75 | 76 | 77 | javax.servlet 78 | javax.servlet-api 79 | 3.0.1 80 | provided 81 | 82 | 83 | 84 | 85 | org.slf4j 86 | slf4j-api 87 | 1.7.12 88 | provided 89 | 90 | 91 | 92 | 93 | 94 | 95 | server 96 | 97 | 98 | 99 | org.apache.maven.plugins 100 | maven-compiler-plugin 101 | 3.3 102 | 103 | ${java.version} 104 | ${java.version} 105 | 106 | 107 | 108 | 109 | 110 | pl.project13.maven 111 | git-commit-id-plugin 112 | 2.1.12 113 | 114 | 115 | 116 | revision 117 | 118 | 119 | 120 | 121 | src/main/resources/git.properties 122 | true 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | org.springframework.boot 131 | spring-boot-starter-data-jpa 132 | 133 | 134 | logback-classic 135 | ch.qos.logback 136 | 137 | 138 | 139 | 140 | 141 | com.mangofactory 142 | swagger-springmvc 143 | 1.0.2 144 | jar 145 | 146 | 147 | -------------------------------------------------------------------------------- /scripts/update-production.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Deploy version to production with a hot-update 4 | # @author Michael Lesniak (mlesniak@micromata.de) 5 | # 6 | # neo.sh from the SDK must be on path 7 | 8 | set -e 9 | 10 | mvn -P production clean package 11 | neo.sh hot-update config.properties --synchronous $* 12 | 13 | -------------------------------------------------------------------------------- /src/main/java/com/mlesniak/sap/playground/EnvironmentContextInitializer.java: -------------------------------------------------------------------------------- 1 | package com.mlesniak.sap.playground; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.context.ApplicationContextInitializer; 6 | import org.springframework.context.ConfigurableApplicationContext; 7 | 8 | /** 9 | * Detects the current landscape the application is run on and initializes the Spring 10 | * {@link ApplicationContext} accordingly. 11 | * 12 | * @see ApplicationContextInitializer 13 | */ 14 | public class EnvironmentContextInitializer implements ApplicationContextInitializer { 15 | private static final Logger logger = LoggerFactory.getLogger(EnvironmentContextInitializer.class); 16 | 17 | public enum RuntimeEnvironment { 18 | DEV, 19 | PRODUCTION 20 | } 21 | 22 | @Override 23 | public void initialize(ConfigurableApplicationContext applicationContext) { 24 | RuntimeEnvironment stage = getEnvironment(); 25 | applicationContext.getEnvironment().setActiveProfiles(stage.name().toLowerCase()); 26 | } 27 | 28 | /** 29 | * Returns the {@link RuntimeEnvironment} the application runs in. Defaults to CLOUD. 30 | * 31 | * @return The {@link RuntimeEnvironment} the application runs in 32 | */ 33 | public static RuntimeEnvironment getEnvironment() { 34 | RuntimeEnvironment retVal = RuntimeEnvironment.PRODUCTION; 35 | 36 | // HC_LANDSCAPE is set on HCP-based environments. 37 | final String landscape = System.getenv("HC_LANDSCAPE"); 38 | if (landscape == null) { 39 | retVal = RuntimeEnvironment.DEV; 40 | } 41 | 42 | logger.info("Application running in '{}' environment", retVal.name().toLowerCase()); 43 | return retVal; 44 | } 45 | } -------------------------------------------------------------------------------- /src/main/java/com/mlesniak/sap/playground/Main.java: -------------------------------------------------------------------------------- 1 | package com.mlesniak.sap.playground; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.boot.builder.SpringApplicationBuilder; 7 | import org.springframework.boot.context.web.SpringBootServletInitializer; 8 | import org.springframework.context.annotation.Bean; 9 | 10 | import com.mangofactory.swagger.configuration.SpringSwaggerConfig; 11 | import com.mangofactory.swagger.models.dto.ApiInfo; 12 | import com.mangofactory.swagger.plugin.EnableSwagger; 13 | import com.mangofactory.swagger.plugin.SwaggerSpringMvcPlugin; 14 | 15 | /** 16 | * Application entry point. 17 | * 18 | * @author Michael Lesniak (mlesniak@micromata.de) 19 | */ 20 | @EnableSwagger 21 | @SpringBootApplication 22 | public class Main extends SpringBootServletInitializer { 23 | @Autowired 24 | private SpringSwaggerConfig springSwaggerConfig; 25 | 26 | @Override 27 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 28 | return application.sources(Main.class); 29 | } 30 | 31 | public static void main(String[] args) { 32 | 33 | SpringApplication app = new SpringApplication(Main.class); 34 | 35 | app.addInitializers(new EnvironmentContextInitializer()); 36 | 37 | app.run(args); 38 | } 39 | 40 | /** 41 | * Configuration options for swagger, the REST API documentation tool. 42 | * 43 | * @return configuration 44 | */ 45 | @Bean 46 | public SwaggerSpringMvcPlugin customImplementation() { 47 | ApiInfo apiInfo = new ApiInfo( 48 | "MessageBoard API documentation", 49 | "Demo application for Spring-Boot and SAP HCP", 50 | "n/a", 51 | "mail@mlesniak.com", 52 | "n/a", 53 | "n/a"); 54 | return new SwaggerSpringMvcPlugin(springSwaggerConfig) 55 | .apiInfo(apiInfo) 56 | .includePatterns("/rest/.*"); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/mlesniak/sap/playground/MainController.java: -------------------------------------------------------------------------------- 1 | package com.mlesniak.sap.playground; 2 | 3 | import com.wordnik.swagger.annotations.ApiOperation; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.web.bind.annotation.PathVariable; 10 | import org.springframework.web.bind.annotation.RequestBody; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RequestMethod; 13 | import org.springframework.web.bind.annotation.RestController; 14 | 15 | /** 16 | * Example controller. 17 | * 18 | * @author Michael Lesniak (mlesniak@micromata.de) 19 | */ 20 | @RestController 21 | @RequestMapping("/rest/text") 22 | public class MainController { 23 | private static final Logger LOG = LoggerFactory.getLogger(MainController.class); 24 | 25 | @Autowired 26 | private TextService textService; 27 | 28 | @ApiOperation("Stores a new text entry") 29 | @RequestMapping(value = "", method = RequestMethod.POST) 30 | public ResponseEntity save(@RequestBody String text) { 31 | LOG.debug("Request to POST:/"); 32 | try { 33 | Long id = textService.save(text); 34 | return new ResponseEntity<>(id, HttpStatus.CREATED); 35 | } catch (IllegalArgumentException e) { 36 | return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); 37 | } 38 | } 39 | 40 | @ApiOperation("Retrieve the list of all stored entries") 41 | @RequestMapping(value = "", method = RequestMethod.GET) 42 | public Iterable find() { 43 | LOG.debug("Request to GET:/"); 44 | return textService.list(); 45 | } 46 | 47 | @ApiOperation("Retrieve a single entry for the given id") 48 | @RequestMapping(value = "/{id}", method = RequestMethod.GET) 49 | public String get(@PathVariable("id") Long id) { 50 | LOG.debug("Request to GET:/{}", id); 51 | return textService.get(id).getText(); 52 | } 53 | } 54 | 55 | -------------------------------------------------------------------------------- /src/main/java/com/mlesniak/sap/playground/TextEntry.java: -------------------------------------------------------------------------------- 1 | package com.mlesniak.sap.playground; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.GeneratedValue; 5 | import javax.persistence.Id; 6 | 7 | /** 8 | * Example entity. 9 | * 10 | * @author Michael Lesniak (mlesniak@micromata.de) 11 | */ 12 | @Entity 13 | public class TextEntry { 14 | @Id 15 | @GeneratedValue 16 | private Long id; 17 | 18 | private String text; 19 | 20 | public Long getId() { 21 | return id; 22 | } 23 | 24 | public void setId(final Long id) { 25 | this.id = id; 26 | } 27 | 28 | public String getText() { 29 | return text; 30 | } 31 | 32 | public void setText(final String text) { 33 | this.text = text; 34 | } 35 | 36 | @Override 37 | public String toString() { 38 | return "TextEntry{" + 39 | "id=" + id + 40 | ", text='" + text + '\'' + 41 | '}'; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/mlesniak/sap/playground/TextRepository.java: -------------------------------------------------------------------------------- 1 | package com.mlesniak.sap.playground; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | /** 6 | * Default repository for text entries. 7 | * 8 | * @author Michael Lesniak (mlesniak@micromata.de) 9 | */ 10 | public interface TextRepository extends CrudRepository { 11 | // Empty 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/mlesniak/sap/playground/TextService.java: -------------------------------------------------------------------------------- 1 | package com.mlesniak.sap.playground; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Service; 7 | 8 | /** 9 | * Simple service layer. 10 | * 11 | * @author Michael Lesniak (mlesniak@micromata.de) 12 | */ 13 | @Service 14 | public class TextService { 15 | private static final Logger LOG = LoggerFactory.getLogger(TextService.class); 16 | 17 | /** Default length of a VARCHAR. */ 18 | private static final int MAX_LENGTH = 255; 19 | 20 | @Autowired 21 | private TextRepository textRepository; 22 | 23 | public Long save(String text) { 24 | if (text.length() > MAX_LENGTH) { 25 | LOG.error("Text too large. length={}", text.length()); 26 | throw new IllegalArgumentException("Text too large"); 27 | } 28 | 29 | LOG.info("Store text={}", text); 30 | TextEntry textEntry = new TextEntry(); 31 | textEntry.setText(text); 32 | textRepository.save(textEntry); 33 | return textEntry.getId(); 34 | } 35 | 36 | public Iterable list() { 37 | LOG.info("List all entries"); 38 | return textRepository.findAll(); 39 | } 40 | 41 | public TextEntry get(Long id) { 42 | LOG.info("Get entry id={}", id); 43 | return textRepository.findOne(id); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/mlesniak/sap/playground/VersionController.java: -------------------------------------------------------------------------------- 1 | package com.mlesniak.sap.playground; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | import java.util.Properties; 8 | 9 | import com.wordnik.swagger.annotations.ApiOperation; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.bind.annotation.RequestMethod; 14 | import org.springframework.web.bind.annotation.RestController; 15 | 16 | /** 17 | * Show version information provided by the git-properties plugin. 18 | * 19 | * @author Michael Lesniak (mlesniak@micromata.de) 20 | */ 21 | @RestController 22 | @RequestMapping("/rest/") 23 | public class VersionController { 24 | private static final Logger LOG = LoggerFactory.getLogger(VersionController.class); 25 | 26 | @ApiOperation("Provides build information") 27 | @RequestMapping(value = "/version", method = RequestMethod.GET) 28 | public Map version() throws IOException { 29 | return getVersionInformation(); 30 | } 31 | 32 | private Map getVersionInformation() throws IOException { 33 | LOG.info("Version request"); 34 | Map info = new HashMap<>(); 35 | InputStream is = VersionController.class.getResourceAsStream("/git.properties"); 36 | if (is == null) { 37 | return info; 38 | } 39 | Properties properties = new Properties(); 40 | properties.load(is); 41 | 42 | for (String key : properties.stringPropertyNames()) { 43 | info.put(key, properties.getProperty(key)); 44 | } 45 | return info; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/resources/application-production.properties: -------------------------------------------------------------------------------- 1 | # Debugging output 2 | debug=false 3 | 4 | 5 | # JNDI-based database connection. Note that you also have to add a corresponding resource in webapp/WEB-INF/web.xml 6 | spring.datasource.jndi-name=java:comp/env/jdbc/DefaultDB 7 | spring.jpa.hibernate.ddl-auto=update 8 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # Debugging output 2 | debug=true 3 | -------------------------------------------------------------------------------- /src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n 19 | 20 | 21 | 22 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/main/resources/public/css/main.css: -------------------------------------------------------------------------------- 1 | /*No rounded corners*/ 2 | .navbar { 3 | border-radius: 0; 4 | } 5 | 6 | /*Add animation*/ 7 | .repeated-item.ng-enter { 8 | animation-name: add; 9 | animation-duration: 1s; 10 | } 11 | 12 | @keyframes add { 13 | from { 14 | opacity: 0; 15 | } 16 | 17 | to { 18 | opacity: 1; 19 | } 20 | } -------------------------------------------------------------------------------- /src/main/resources/public/i18n/messages_de.json: -------------------------------------------------------------------------------- 1 | { 2 | "menu.name": "Schwarzes Brett", 3 | "menu.language": "Sprache", 4 | "menu.documentation": "API Dokumentation", 5 | "menu.source": "Quellcode", 6 | "menu.author": "Autor", 7 | "menu.version": "Version", 8 | "inputMessage": "Nachricht eingeben", 9 | "lang.en": "Englisch", 10 | "lang.de": "Deutsch" 11 | } -------------------------------------------------------------------------------- /src/main/resources/public/i18n/messages_en.json: -------------------------------------------------------------------------------- 1 | { 2 | "menu.name": "Message board", 3 | "menu.language": "Language", 4 | "menu.documentation": "API documentation", 5 | "menu.source": "Source code", 6 | "menu.author": "Author", 7 | "menu.version": "Version", 8 | "inputMessage": "Enter message", 9 | "lang.en": "English", 10 | "lang.de": "German" 11 | } -------------------------------------------------------------------------------- /src/main/resources/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Demo page 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 45 | 46 | 47 |
48 | 49 | 50 |
51 |
52 | 54 |
55 |
56 | 57 | 58 |
59 | 60 | 61 | 62 | 63 |
{{entry.text}}
64 | 65 |
66 | 67 | -------------------------------------------------------------------------------- /src/main/resources/public/js/application.js: -------------------------------------------------------------------------------- 1 | /** 2 | * AngularJS frontend logic. 3 | * 4 | * Since this is so small, we do not separate services, etc. into other files. 5 | * 6 | * @author Michael Lesniak (mlesniak@micromata.de) 7 | */ 8 | 9 | var demoApp = angular.module('messageBoard', [ 10 | 'ngResource', 11 | 'pascalprecht.translate', 12 | 'ui.bootstrap', 13 | 'ngAnimate' 14 | ]); 15 | 16 | // Create resource for RESTful endpoint. 17 | demoApp.factory('Entry', function ($resource) { 18 | return $resource('rest/text/:id'); 19 | }); 20 | 21 | // I18N 22 | demoApp.config(['$translateProvider', function ($translateProvider) { 23 | $translateProvider.useStaticFilesLoader({ 24 | prefix: 'i18n/messages_', 25 | suffix: '.json' 26 | }); 27 | $translateProvider.preferredLanguage('en'); 28 | }]); 29 | 30 | 31 | demoApp.controller('LanguageCtrl', function ($scope, $translate) { 32 | // Available languages 33 | $scope.items = [ 34 | 'de', 35 | 'en' 36 | ]; 37 | 38 | $scope.use = function (lang) { 39 | $translate.use(lang); 40 | } 41 | }); 42 | 43 | demoApp.controller('DemoCtrl', function ($scope, Entry, $translate) { 44 | function load() { 45 | Entry.query(function (data) { 46 | $scope.texts = data; 47 | }); 48 | } 49 | 50 | $scope.submit = function () { 51 | var input = $scope.input; 52 | if (input == '') { 53 | return; 54 | } 55 | 56 | // Send raw data to the endpoint. 57 | Entry.save(input, function (data) { 58 | var text = { 59 | "text": input, 60 | "id": data 61 | }; 62 | $scope.texts.push(text); 63 | $scope.input = ''; 64 | }); 65 | }; 66 | 67 | // Initial loading. 68 | load(); 69 | }); -------------------------------------------------------------------------------- /src/main/resources/public/swagger/css/reset.css: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ v2.0 | 20110126 */ 2 | html, 3 | body, 4 | div, 5 | span, 6 | applet, 7 | object, 8 | iframe, 9 | h1, 10 | h2, 11 | h3, 12 | h4, 13 | h5, 14 | h6, 15 | p, 16 | blockquote, 17 | pre, 18 | a, 19 | abbr, 20 | acronym, 21 | address, 22 | big, 23 | cite, 24 | code, 25 | del, 26 | dfn, 27 | em, 28 | img, 29 | ins, 30 | kbd, 31 | q, 32 | s, 33 | samp, 34 | small, 35 | strike, 36 | strong, 37 | sub, 38 | sup, 39 | tt, 40 | var, 41 | b, 42 | u, 43 | i, 44 | center, 45 | dl, 46 | dt, 47 | dd, 48 | ol, 49 | ul, 50 | li, 51 | fieldset, 52 | form, 53 | label, 54 | legend, 55 | table, 56 | caption, 57 | tbody, 58 | tfoot, 59 | thead, 60 | tr, 61 | th, 62 | td, 63 | article, 64 | aside, 65 | canvas, 66 | details, 67 | embed, 68 | figure, 69 | figcaption, 70 | footer, 71 | header, 72 | hgroup, 73 | menu, 74 | nav, 75 | output, 76 | ruby, 77 | section, 78 | summary, 79 | time, 80 | mark, 81 | audio, 82 | video { 83 | margin: 0; 84 | padding: 0; 85 | border: 0; 86 | font-size: 100%; 87 | font: inherit; 88 | vertical-align: baseline; 89 | } 90 | 91 | /* HTML5 display-role reset for older browsers */ 92 | article, 93 | aside, 94 | details, 95 | figcaption, 96 | figure, 97 | footer, 98 | header, 99 | hgroup, 100 | menu, 101 | nav, 102 | section { 103 | display: block; 104 | } 105 | 106 | body { 107 | line-height: 1; 108 | } 109 | 110 | ol, 111 | ul { 112 | list-style: none; 113 | } 114 | 115 | blockquote, 116 | q { 117 | quotes: none; 118 | } 119 | 120 | blockquote:before, 121 | blockquote:after, 122 | q:before, 123 | q:after { 124 | content: ''; 125 | content: none; 126 | } 127 | 128 | table { 129 | border-collapse: collapse; 130 | border-spacing: 0; 131 | } 132 | -------------------------------------------------------------------------------- /src/main/resources/public/swagger/css/style.css: -------------------------------------------------------------------------------- 1 | .swagger-section #header a#logo { 2 | font-size: 1.5em; 3 | font-weight: bold; 4 | text-decoration: none; 5 | background: transparent url(../images/logo.png) no-repeat left center; 6 | padding: 20px 0 20px 40px; 7 | } 8 | 9 | #text-head { 10 | font-size: 80px; 11 | font-family: 'Roboto', sans-serif; 12 | color: #ffffff; 13 | float: right; 14 | margin-right: 20%; 15 | } 16 | 17 | .navbar-fixed-top .navbar-nav { 18 | height: auto; 19 | } 20 | 21 | .navbar-fixed-top .navbar-brand { 22 | height: auto; 23 | } 24 | 25 | .navbar-header { 26 | height: auto; 27 | } 28 | 29 | .navbar-inverse { 30 | background-color: #000; 31 | border-color: #000; 32 | } 33 | 34 | #navbar-brand { 35 | margin-left: 20%; 36 | } 37 | 38 | .navtext { 39 | font-size: 10px; 40 | } 41 | 42 | .h1, 43 | h1 { 44 | font-size: 60px; 45 | } 46 | 47 | .navbar-default .navbar-header .navbar-brand { 48 | color: #a2dfee; 49 | } 50 | 51 | /* tag titles */ 52 | .swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a { 53 | color: #393939; 54 | font-family: 'Arvo', serif; 55 | font-size: 1.5em; 56 | } 57 | 58 | .swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a:hover { 59 | color: black; 60 | } 61 | 62 | .swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 { 63 | color: #525252; 64 | padding-left: 0px; 65 | display: block; 66 | clear: none; 67 | float: left; 68 | font-family: 'Arvo', serif; 69 | font-weight: bold; 70 | } 71 | 72 | .navbar-default .navbar-collapse, 73 | .navbar-default .navbar-form { 74 | border-color: #0A0A0A; 75 | } 76 | 77 | .container1 { 78 | width: 1500px; 79 | margin: auto; 80 | margin-top: 0; 81 | background-image: url('../images/shield.png'); 82 | background-repeat: no-repeat; 83 | background-position: -40px -20px; 84 | margin-bottom: 210px; 85 | } 86 | 87 | .container-inner { 88 | width: 1200px; 89 | margin: auto; 90 | background-color: rgba(223, 227, 228, 0.75); 91 | padding-bottom: 40px; 92 | padding-top: 40px; 93 | border-radius: 15px; 94 | } 95 | 96 | .header-content { 97 | padding: 0; 98 | width: 1000px; 99 | } 100 | 101 | .title1 { 102 | font-size: 80px; 103 | font-family: 'Vollkorn', serif; 104 | color: #404040; 105 | text-align: center; 106 | padding-top: 40px; 107 | padding-bottom: 100px; 108 | } 109 | 110 | #icon { 111 | margin-top: -18px; 112 | } 113 | 114 | .subtext { 115 | font-size: 25px; 116 | font-style: italic; 117 | color: #08b; 118 | text-align: right; 119 | padding-right: 250px; 120 | } 121 | 122 | .bg-primary { 123 | background-color: #00468b; 124 | } 125 | 126 | .navbar-default .nav > li > a, 127 | .navbar-default .nav > li > a:focus { 128 | color: #08b; 129 | } 130 | 131 | .navbar-default .nav > li > a, 132 | .navbar-default .nav > li > a:hover { 133 | color: #08b; 134 | } 135 | 136 | .navbar-default .nav > li > a, 137 | .navbar-default .nav > li > a:focus:hover { 138 | color: #08b; 139 | } 140 | 141 | .text-faded { 142 | font-size: 25px; 143 | font-family: 'Vollkorn', serif; 144 | } 145 | 146 | .section-heading { 147 | font-family: 'Vollkorn', serif; 148 | font-size: 45px; 149 | padding-bottom: 10px; 150 | } 151 | 152 | hr { 153 | border-color: #00468b; 154 | padding-bottom: 10px; 155 | } 156 | 157 | .description { 158 | margin-top: 20px; 159 | padding-bottom: 200px; 160 | } 161 | 162 | .description li { 163 | font-family: 'Vollkorn', serif; 164 | font-size: 25px; 165 | color: #525252; 166 | margin-left: 28%; 167 | padding-top: 5px; 168 | } 169 | 170 | .gap { 171 | margin-top: 200px; 172 | } 173 | 174 | .troubleshootingtext { 175 | color: rgba(255, 255, 255, 0.7); 176 | padding-left: 30%; 177 | } 178 | 179 | .troubleshootingtext li { 180 | list-style-type: circle; 181 | font-size: 25px; 182 | padding-bottom: 5px; 183 | } 184 | 185 | .overlay { 186 | position: absolute; 187 | top: 0; 188 | left: 0; 189 | width: 100%; 190 | height: 100%; 191 | z-index: 1000; 192 | } 193 | 194 | .block.response_body.json:hover { 195 | cursor: pointer; 196 | } 197 | 198 | .backdrop { 199 | color: blue; 200 | } 201 | 202 | #myModal { 203 | height: 100%; 204 | } 205 | 206 | .modal-backdrop { 207 | bottom: 0; 208 | position: fixed; 209 | } 210 | 211 | .curl { 212 | padding: 10px; 213 | font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; 214 | font-size: 0.9em; 215 | max-height: 400px; 216 | margin-top: 5px; 217 | overflow-y: auto; 218 | background-color: #fcf6db; 219 | border: 1px solid #e5e0c6; 220 | border-radius: 4px; 221 | } 222 | 223 | .curl_title { 224 | font-size: 1.1em; 225 | margin: 0; 226 | padding: 15px 0 5px; 227 | font-family: 'Open Sans', 'Helvetica Neue', Arial, sans-serif; 228 | font-weight: 500; 229 | line-height: 1.1; 230 | } 231 | 232 | .footer { 233 | display: none; 234 | } 235 | 236 | .swagger-section .swagger-ui-wrap h2 { 237 | padding: 0; 238 | } 239 | 240 | h2 { 241 | margin: 0; 242 | margin-bottom: 5px; 243 | } 244 | 245 | .markdown p { 246 | font-size: 15px; 247 | font-family: 'Arvo', serif; 248 | } 249 | 250 | .swagger-section .swagger-ui-wrap .code { 251 | font-size: 15px; 252 | font-family: 'Arvo', serif; 253 | } 254 | 255 | .swagger-section .swagger-ui-wrap b { 256 | font-family: 'Arvo', serif; 257 | } 258 | 259 | #signin:hover { 260 | cursor: pointer; 261 | } 262 | 263 | .dropdown-menu { 264 | padding: 15px; 265 | } 266 | 267 | .navbar-right .dropdown-menu { 268 | left: 0; 269 | right: auto; 270 | } 271 | 272 | #signinbutton { 273 | width: 100%; 274 | height: 32px; 275 | font-size: 13px; 276 | font-weight: bold; 277 | color: #08b; 278 | } 279 | 280 | .navbar-default .nav > li .details { 281 | color: #000000; 282 | text-transform: none; 283 | font-size: 15px; 284 | font-weight: normal; 285 | font-family: 'Open Sans', sans-serif; 286 | font-style: italic; 287 | line-height: 20px; 288 | top: -2px; 289 | } 290 | 291 | .navbar-default .nav > li .details:hover { 292 | color: black; 293 | } 294 | 295 | #signout { 296 | width: 100%; 297 | height: 32px; 298 | font-size: 13px; 299 | font-weight: bold; 300 | color: #08b; 301 | } 302 | -------------------------------------------------------------------------------- /src/main/resources/public/swagger/css/typography.css: -------------------------------------------------------------------------------- 1 | /* Google Font's Droid Sans */ 2 | @font-face { 3 | font-family: 'Droid Sans'; 4 | font-style: normal; 5 | font-weight: 400; 6 | src: local('Droid Sans'), local('DroidSans'), url('../fonts/DroidSans.ttf') format('truetype'); 7 | } 8 | 9 | /* Google Font's Droid Sans Bold */ 10 | @font-face { 11 | font-family: 'Droid Sans'; 12 | font-style: normal; 13 | font-weight: 700; 14 | src: local('Droid Sans Bold'), local('DroidSans-Bold'), url('../fonts/DroidSans-Bold.ttf') format('truetype'); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/resources/public/swagger/fonts/DroidSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steinermatt/spring-boot-sap/abe65319a9732e08da29bb0c37f135e7ae879852/src/main/resources/public/swagger/fonts/DroidSans-Bold.ttf -------------------------------------------------------------------------------- /src/main/resources/public/swagger/fonts/DroidSans.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steinermatt/spring-boot-sap/abe65319a9732e08da29bb0c37f135e7ae879852/src/main/resources/public/swagger/fonts/DroidSans.ttf -------------------------------------------------------------------------------- /src/main/resources/public/swagger/images/explorer_icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steinermatt/spring-boot-sap/abe65319a9732e08da29bb0c37f135e7ae879852/src/main/resources/public/swagger/images/explorer_icons.png -------------------------------------------------------------------------------- /src/main/resources/public/swagger/images/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steinermatt/spring-boot-sap/abe65319a9732e08da29bb0c37f135e7ae879852/src/main/resources/public/swagger/images/favicon-16x16.png -------------------------------------------------------------------------------- /src/main/resources/public/swagger/images/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steinermatt/spring-boot-sap/abe65319a9732e08da29bb0c37f135e7ae879852/src/main/resources/public/swagger/images/favicon-32x32.png -------------------------------------------------------------------------------- /src/main/resources/public/swagger/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steinermatt/spring-boot-sap/abe65319a9732e08da29bb0c37f135e7ae879852/src/main/resources/public/swagger/images/favicon.ico -------------------------------------------------------------------------------- /src/main/resources/public/swagger/images/logo_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steinermatt/spring-boot-sap/abe65319a9732e08da29bb0c37f135e7ae879852/src/main/resources/public/swagger/images/logo_small.png -------------------------------------------------------------------------------- /src/main/resources/public/swagger/images/pet_store_api.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steinermatt/spring-boot-sap/abe65319a9732e08da29bb0c37f135e7ae879852/src/main/resources/public/swagger/images/pet_store_api.png -------------------------------------------------------------------------------- /src/main/resources/public/swagger/images/throbber.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steinermatt/spring-boot-sap/abe65319a9732e08da29bb0c37f135e7ae879852/src/main/resources/public/swagger/images/throbber.gif -------------------------------------------------------------------------------- /src/main/resources/public/swagger/images/wordnik_api.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steinermatt/spring-boot-sap/abe65319a9732e08da29bb0c37f135e7ae879852/src/main/resources/public/swagger/images/wordnik_api.png -------------------------------------------------------------------------------- /src/main/resources/public/swagger/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Swagger UI 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 102 | 103 | 104 | 105 | 117 | 118 |
 
119 |
120 | 121 | 122 | -------------------------------------------------------------------------------- /src/main/resources/public/swagger/lang/en.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated": "Warning: Deprecated", 6 | "Implementation Notes": "Implementation Notes", 7 | "Response Class": "Response Class", 8 | "Status": "Status", 9 | "Parameters": "Parameters", 10 | "Parameter": "Parameter", 11 | "Value": "Value", 12 | "Description": "Description", 13 | "Parameter Type": "Parameter Type", 14 | "Data Type": "Data Type", 15 | "Response Messages": "Response Messages", 16 | "HTTP Status Code": "HTTP Status Code", 17 | "Reason": "Reason", 18 | "Response Model": "Response Model", 19 | "Request URL": "Request URL", 20 | "Response Body": "Response Body", 21 | "Response Code": "Response Code", 22 | "Response Headers": "Response Headers", 23 | "Hide Response": "Hide Response", 24 | "Headers": "Headers", 25 | "Try it out!": "Try it out!", 26 | "Show/Hide": "Show/Hide", 27 | "List Operations": "List Operations", 28 | "Expand Operations": "Expand Operations", 29 | "Raw": "Raw", 30 | "can't parse JSON. Raw result": "can't parse JSON. Raw result", 31 | "Model Schema": "Model Schema", 32 | "Model": "Model", 33 | "apply": "apply", 34 | "Username": "Username", 35 | "Password": "Password", 36 | "Terms of service": "Terms of service", 37 | "Created by": "Created by", 38 | "See more at": "See more at", 39 | "Contact the developer": "Contact the developer", 40 | "api version": "api version", 41 | "Response Content Type": "Response Content Type", 42 | "fetching resource": "fetching resource", 43 | "fetching resource list": "fetching resource list", 44 | "Explore": "Explore", 45 | "Show Swagger Petstore Example Apis": "Show Swagger Petstore Example Apis", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.": "Can't read from server. It may not have the appropriate access-control-origin settings.", 47 | "Please specify the protocol for": "Please specify the protocol for", 48 | "Can't read swagger JSON from": "Can't read swagger JSON from", 49 | "Finished Loading Resource Information. Rendering Swagger UI": "Finished Loading Resource Information. Rendering Swagger UI", 50 | "Unable to read api": "Unable to read api", 51 | "from path": "from path", 52 | "server returned": "server returned" 53 | }); 54 | -------------------------------------------------------------------------------- /src/main/resources/public/swagger/lang/es.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Advertencia: Obsoleto", 6 | "Implementation Notes":"Notas de implementación", 7 | "Response Class":"Clase de la Respuesta", 8 | "Status":"Status", 9 | "Parameters":"Parámetros", 10 | "Parameter":"Parámetro", 11 | "Value":"Valor", 12 | "Description":"Descripción", 13 | "Parameter Type":"Tipo del Parámetro", 14 | "Data Type":"Tipo del Dato", 15 | "Response Messages":"Mensajes de la Respuesta", 16 | "HTTP Status Code":"Código de Status HTTP", 17 | "Reason":"Razón", 18 | "Response Model":"Modelo de la Respuesta", 19 | "Request URL":"URL de la Solicitud", 20 | "Response Body":"Cuerpo de la Respuesta", 21 | "Response Code":"Código de la Respuesta", 22 | "Response Headers":"Encabezados de la Respuesta", 23 | "Hide Response":"Ocultar Respuesta", 24 | "Try it out!":"Pruébalo!", 25 | "Show/Hide":"Mostrar/Ocultar", 26 | "List Operations":"Listar Operaciones", 27 | "Expand Operations":"Expandir Operaciones", 28 | "Raw":"Crudo", 29 | "can't parse JSON. Raw result":"no puede parsear el JSON. Resultado crudo", 30 | "Model Schema":"Esquema del Modelo", 31 | "Model":"Modelo", 32 | "apply":"aplicar", 33 | "Username":"Nombre de usuario", 34 | "Password":"Contraseña", 35 | "Terms of service":"Términos de Servicio", 36 | "Created by":"Creado por", 37 | "See more at":"Ver más en", 38 | "Contact the developer":"Contactar al desarrollador", 39 | "api version":"versión de la api", 40 | "Response Content Type":"Tipo de Contenido (Content Type) de la Respuesta", 41 | "fetching resource":"buscando recurso", 42 | "fetching resource list":"buscando lista del recurso", 43 | "Explore":"Explorar", 44 | "Show Swagger Petstore Example Apis":"Mostrar Api Ejemplo de Swagger Petstore", 45 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"No se puede leer del servidor. Tal vez no tiene la configuración de control de acceso de origen (access-control-origin) apropiado.", 46 | "Please specify the protocol for":"Por favor, especificar el protocola para", 47 | "Can't read swagger JSON from":"No se puede leer el JSON de swagger desde", 48 | "Finished Loading Resource Information. Rendering Swagger UI":"Finalizada la carga del recurso de Información. Mostrando Swagger UI", 49 | "Unable to read api":"No se puede leer la api", 50 | "from path":"desde ruta", 51 | "server returned":"el servidor retornó" 52 | }); 53 | -------------------------------------------------------------------------------- /src/main/resources/public/swagger/lang/fr.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated": "Avertissement : Obsolète", 6 | "Implementation Notes": "Notes d'implementation", 7 | "Response Class": "Classe de la réponse", 8 | "Status": "Statut", 9 | "Parameters": "Paramètres", 10 | "Parameter": "Paramètre", 11 | "Value": "Valeur", 12 | "Description": "Description", 13 | "Parameter Type": "Type du paramètre", 14 | "Data Type": "Type de données", 15 | "Response Messages": "Messages de la réponse", 16 | "HTTP Status Code": "Code de statut HTTP", 17 | "Reason": "Raison", 18 | "Response Model": "Modèle de réponse", 19 | "Request URL": "URL appelée", 20 | "Response Body": "Corps de la réponse", 21 | "Response Code": "Code de la réponse", 22 | "Response Headers": "En-têtes de la réponse", 23 | "Hide Response": "Cacher la réponse", 24 | "Headers": "En-têtes", 25 | "Try it out!": "Testez !", 26 | "Show/Hide": "Afficher/Masquer", 27 | "List Operations": "Liste des opérations", 28 | "Expand Operations": "Développer les opérations", 29 | "Raw": "Brut", 30 | "can't parse JSON. Raw result": "impossible de décoder le JSON. Résultat brut", 31 | "Model Schema": "Définition du modèle", 32 | "Model": "Modèle", 33 | "apply": "appliquer", 34 | "Username": "Nom d'utilisateur", 35 | "Password": "Mot de passe", 36 | "Terms of service": "Conditions de service", 37 | "Created by": "Créé par", 38 | "See more at": "Voir plus sur", 39 | "Contact the developer": "Contacter le développeur", 40 | "api version": "version de l'api", 41 | "Response Content Type": "Content Type de la réponse", 42 | "fetching resource": "récupération de la ressource", 43 | "fetching resource list": "récupération de la liste de ressources", 44 | "Explore": "Explorer", 45 | "Show Swagger Petstore Example Apis": "Montrer les Apis de l'exemple Petstore de Swagger", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.": "Impossible de lire à partir du serveur. Il se peut que les réglages access-control-origin ne soient pas appropriés.", 47 | "Please specify the protocol for": "Veuillez spécifier un protocole pour", 48 | "Can't read swagger JSON from": "Impossible de lire le JSON swagger à partir de", 49 | "Finished Loading Resource Information. Rendering Swagger UI": "Chargement des informations terminé. Affichage de Swagger UI", 50 | "Unable to read api": "Impossible de lire l'api", 51 | "from path": "à partir du chemin", 52 | "server returned": "réponse du serveur" 53 | }); 54 | -------------------------------------------------------------------------------- /src/main/resources/public/swagger/lang/it.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated": "Attenzione: Deprecato", 6 | "Implementation Notes": "Note di implementazione", 7 | "Response Class": "Classe della risposta", 8 | "Status": "Stato", 9 | "Parameters": "Parametri", 10 | "Parameter": "Parametro", 11 | "Value": "Valore", 12 | "Description": "Descrizione", 13 | "Parameter Type": "Tipo di parametro", 14 | "Data Type": "Tipo di dato", 15 | "Response Messages": "Messaggi della risposta", 16 | "HTTP Status Code": "Codice stato HTTP", 17 | "Reason": "Motivo", 18 | "Response Model": "Modello di risposta", 19 | "Request URL": "URL della richiesta", 20 | "Response Body": "Corpo della risposta", 21 | "Response Code": "Oggetto della risposta", 22 | "Response Headers": "Intestazioni della risposta", 23 | "Hide Response": "Nascondi risposta", 24 | "Try it out!": "Provalo!", 25 | "Show/Hide": "Mostra/Nascondi", 26 | "List Operations": "Mostra operazioni", 27 | "Expand Operations": "Espandi operazioni", 28 | "Raw": "Grezzo (raw)", 29 | "can't parse JSON. Raw result": "non è possibile parsare il JSON. Risultato grezzo (raw).", 30 | "Model Schema": "Schema del modello", 31 | "Model": "Modello", 32 | "apply": "applica", 33 | "Username": "Nome utente", 34 | "Password": "Password", 35 | "Terms of service": "Condizioni del servizio", 36 | "Created by": "Creato da", 37 | "See more at": "Informazioni aggiuntive:", 38 | "Contact the developer": "Contatta lo sviluppatore", 39 | "api version": "versione api", 40 | "Response Content Type": "Tipo di contenuto (content type) della risposta", 41 | "fetching resource": "recuperando la risorsa", 42 | "fetching resource list": "recuperando lista risorse", 43 | "Explore": "Esplora", 44 | "Show Swagger Petstore Example Apis": "Mostra le api di esempio di Swagger Petstore", 45 | "Can't read from server. It may not have the appropriate access-control-origin settings.": "Non è possibile leggere dal server. Potrebbe non avere le impostazioni di controllo accesso origine (access-control-origin) appropriate.", 46 | "Please specify the protocol for": "Si prega di specificare il protocollo per", 47 | "Can't read swagger JSON from": "Impossibile leggere JSON swagger da:", 48 | "Finished Loading Resource Information. Rendering Swagger UI": "Lettura informazioni risorse termianta. Swagger UI viene mostrata", 49 | "Unable to read api": "Impossibile leggere la api", 50 | "from path": "da cartella", 51 | "server returned": "il server ha restituito" 52 | }); 53 | -------------------------------------------------------------------------------- /src/main/resources/public/swagger/lang/ja.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated": "警告: 廃止予定", 6 | "Implementation Notes": "実装メモ", 7 | "Response Class": "レスポンスクラス", 8 | "Status": "ステータス", 9 | "Parameters": "パラメータ群", 10 | "Parameter": "パラメータ", 11 | "Value": "値", 12 | "Description": "説明", 13 | "Parameter Type": "パラメータタイプ", 14 | "Data Type": "データタイプ", 15 | "Response Messages": "レスポンスメッセージ", 16 | "HTTP Status Code": "HTTPステータスコード", 17 | "Reason": "理由", 18 | "Response Model": "レスポンスモデル", 19 | "Request URL": "リクエストURL", 20 | "Response Body": "レスポンスボディ", 21 | "Response Code": "レスポンスコード", 22 | "Response Headers": "レスポンスヘッダ", 23 | "Hide Response": "レスポンスを隠す", 24 | "Headers": "ヘッダ", 25 | "Try it out!": "実際に実行!", 26 | "Show/Hide": "表示/非表示", 27 | "List Operations": "操作一覧", 28 | "Expand Operations": "操作の展開", 29 | "Raw": "Raw", 30 | "can't parse JSON. Raw result": "JSONへ解釈できません. 未加工の結果", 31 | "Model Schema": "モデルスキーマ", 32 | "Model": "モデル", 33 | "apply": "実行", 34 | "Username": "ユーザ名", 35 | "Password": "パスワード", 36 | "Terms of service": "サービス利用規約", 37 | "Created by": "Created by", 38 | "See more at": "See more at", 39 | "Contact the developer": "開発者に連絡", 40 | "api version": "APIバージョン", 41 | "Response Content Type": "レスポンス コンテンツタイプ", 42 | "fetching resource": "リソースの取得", 43 | "fetching resource list": "リソース一覧の取得", 44 | "Explore": "Explore", 45 | "Show Swagger Petstore Example Apis": "SwaggerペットストアAPIの表示", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.": "サーバから読み込めません. 適切なaccess-control-origin設定を持っていない可能性があります.", 47 | "Please specify the protocol for": "プロトコルを指定してください", 48 | "Can't read swagger JSON from": "次からswagger JSONを読み込めません", 49 | "Finished Loading Resource Information. Rendering Swagger UI": "リソース情報の読み込みが完了しました. Swagger UIを描画しています", 50 | "Unable to read api": "APIを読み込めません", 51 | "from path": "次のパスから", 52 | "server returned": "サーバからの返答" 53 | }); 54 | -------------------------------------------------------------------------------- /src/main/resources/public/swagger/lang/pt.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated": "Aviso: Depreciado", 6 | "Implementation Notes": "Notas de Implementação", 7 | "Response Class": "Classe de resposta", 8 | "Status": "Status", 9 | "Parameters": "Parâmetros", 10 | "Parameter": "Parâmetro", 11 | "Value": "Valor", 12 | "Description": "Descrição", 13 | "Parameter Type": "Tipo de parâmetro", 14 | "Data Type": "Tipo de dados", 15 | "Response Messages": "Mensagens de resposta", 16 | "HTTP Status Code": "Código de status HTTP", 17 | "Reason": "Razão", 18 | "Response Model": "Modelo resposta", 19 | "Request URL": "URL requisição", 20 | "Response Body": "Corpo da resposta", 21 | "Response Code": "Código da resposta", 22 | "Response Headers": "Cabeçalho da resposta", 23 | "Headers": "Cabeçalhos", 24 | "Hide Response": "Esconder resposta", 25 | "Try it out!": "Tente agora!", 26 | "Show/Hide": "Mostrar/Esconder", 27 | "List Operations": "Listar operações", 28 | "Expand Operations": "Expandir operações", 29 | "Raw": "Cru", 30 | "can't parse JSON. Raw result": "Falha ao analisar JSON. Resulto cru", 31 | "Model Schema": "Modelo esquema", 32 | "Model": "Modelo", 33 | "apply": "Aplicar", 34 | "Username": "Usuário", 35 | "Password": "Senha", 36 | "Terms of service": "Termos do serviço", 37 | "Created by": "Criado por", 38 | "See more at": "Veja mais em", 39 | "Contact the developer": "Contate o desenvolvedor", 40 | "api version": "Versão api", 41 | "Response Content Type": "Tipo de conteúdo da resposta", 42 | "fetching resource": "busca recurso", 43 | "fetching resource list": "buscando lista de recursos", 44 | "Explore": "Explorar", 45 | "Show Swagger Petstore Example Apis": "Show Swagger Petstore Example Apis", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.": "Não é possível ler do servidor. Pode não ter as apropriadas configurações access-control-origin", 47 | "Please specify the protocol for": "Por favor especifique o protocolo", 48 | "Can't read swagger JSON from": "Não é possível ler o JSON Swagger de", 49 | "Finished Loading Resource Information. Rendering Swagger UI": "Carregar informação de recurso finalizada. Renderizando Swagger UI", 50 | "Unable to read api": "Não foi possível ler api", 51 | "from path": "do caminho", 52 | "server returned": "servidor retornou" 53 | }); 54 | -------------------------------------------------------------------------------- /src/main/resources/public/swagger/lang/ru.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Ворнинг: Депрекейтед", 6 | "Implementation Notes":"Заметки", 7 | "Response Class":"Пример ответа", 8 | "Status":"Статус", 9 | "Parameters":"Параметры", 10 | "Parameter":"Параметр", 11 | "Value":"Значение", 12 | "Description":"Описание", 13 | "Parameter Type":"Тип параметра", 14 | "Data Type":"Тип данных", 15 | "HTTP Status Code":"HTTP код", 16 | "Reason":"Причина", 17 | "Response Model":"Структура ответа", 18 | "Request URL":"URL запроса", 19 | "Response Body":"Тело ответа", 20 | "Response Code":"HTTP код ответа", 21 | "Response Headers":"Заголовки ответа", 22 | "Hide Response":"Спрятать ответ", 23 | "Response Messages":"Что может прийти в ответ", 24 | "Try it out!":"Попробовать!", 25 | "Show/Hide":"Показать/Скрыть", 26 | "List Operations":"Операции кратко", 27 | "Expand Operations":"Операции подробно", 28 | "Raw":"В сыром виде", 29 | "can't parse JSON. Raw result":"Не удается распарсить ответ:", 30 | "Model Schema":"Структура", 31 | "Model":"Описание", 32 | "apply":"применить", 33 | "Username":"Имя пользователя", 34 | "Password":"Пароль", 35 | "Terms of service":"Условия использования", 36 | "Created by":"Разработано", 37 | "See more at":"Еще тут", 38 | "Contact the developer":"Связаться с разработчиком", 39 | "api version":"Версия API", 40 | "Response Content Type":"Content Type ответа", 41 | "fetching resource":"Получение ресурса", 42 | "fetching resource list":"Получение ресурсов", 43 | "Explore":"Поехали", 44 | "Show Swagger Petstore Example Apis":"Показать примеры АПИ", 45 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Не удается получить ответ от сервера. Возможно, какая-то лажа с настройками доступа", 46 | "Please specify the protocol for":"Пожалуйста, укажите протогол для", 47 | "Can't read swagger JSON from":"Не получается прочитать swagger json из", 48 | "Finished Loading Resource Information. Rendering Swagger UI":"Загрузка информации о ресурсах завершена. Рендерим", 49 | "Unable to read api":"Не удалось прочитать api", 50 | "from path":"по адресу", 51 | "server returned":"сервер сказал" 52 | }); 53 | -------------------------------------------------------------------------------- /src/main/resources/public/swagger/lang/tr.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated": "Uyarı: Deprecated", 6 | "Implementation Notes": "Gerçekleştirim Notları", 7 | "Response Class": "Dönen Sınıf", 8 | "Status": "Statü", 9 | "Parameters": "Parametreler", 10 | "Parameter": "Parametre", 11 | "Value": "Değer", 12 | "Description": "Açıklama", 13 | "Parameter Type": "Parametre Tipi", 14 | "Data Type": "Veri Tipi", 15 | "Response Messages": "Dönüş Mesajı", 16 | "HTTP Status Code": "HTTP Statü Kodu", 17 | "Reason": "Gerekçe", 18 | "Response Model": "Dönüş Modeli", 19 | "Request URL": "İstek URL", 20 | "Response Body": "Dönüş İçeriği", 21 | "Response Code": "Dönüş Kodu", 22 | "Response Headers": "Dönüş Üst Bilgileri", 23 | "Hide Response": "Dönüşü Gizle", 24 | "Headers": "Üst Bilgiler", 25 | "Try it out!": "Dene!", 26 | "Show/Hide": "Göster/Gizle", 27 | "List Operations": "Operasyonları Listele", 28 | "Expand Operations": "Operasyonları Aç", 29 | "Raw": "Ham", 30 | "can't parse JSON. Raw result": "JSON çözümlenemiyor. Ham sonuç", 31 | "Model Schema": "Model Şema", 32 | "Model": "Model", 33 | "apply": "uygula", 34 | "Username": "Kullanıcı Adı", 35 | "Password": "Parola", 36 | "Terms of service": "Servis şartları", 37 | "Created by": "Oluşturan", 38 | "See more at": "Daha fazlası için", 39 | "Contact the developer": "Geliştirici ile İletişime Geçin", 40 | "api version": "api versiyon", 41 | "Response Content Type": "Dönüş İçerik Tipi", 42 | "fetching resource": "kaynak getiriliyor", 43 | "fetching resource list": "kaynak listesi getiriliyor", 44 | "Explore": "Keşfet", 45 | "Show Swagger Petstore Example Apis": "Swagger Petstore Örnek Api'yi Gör", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.": "Sunucudan okuma yapılamıyor. Sunucu access-control-origin ayarlarınızı kontrol edin.", 47 | "Please specify the protocol for": "Lütfen istenen adres için protokol belirtiniz", 48 | "Can't read swagger JSON from": "Swagger JSON bu kaynaktan okunamıyor", 49 | "Finished Loading Resource Information. Rendering Swagger UI": "Kaynak baglantısı tamamlandı. Swagger UI gösterime hazırlanıyor", 50 | "Unable to read api": "api okunamadı", 51 | "from path": "yoldan", 52 | "server returned": "sunucuya dönüldü" 53 | }); 54 | -------------------------------------------------------------------------------- /src/main/resources/public/swagger/lang/translator.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Translator for documentation pages. 5 | * 6 | * To enable translation you should include one of language-files in your index.html 7 | * after . 8 | * For example - 9 | * 10 | * If you wish to translate some new texsts you should do two things: 11 | * 1. Add a new phrase pair ("New Phrase": "New Translation") into your language file (for example lang/ru.js). It will be great if you add it in other language files too. 12 | * 2. Mark that text it templates this way New Phrase or . 13 | * The main thing here is attribute data-sw-translate. Only inner html, title-attribute and value-attribute are going to translate. 14 | * 15 | */ 16 | window.SwaggerTranslator = { 17 | 18 | _words: [], 19 | 20 | translate: function (sel) { 21 | var $this = this; 22 | sel = sel || '[data-sw-translate]'; 23 | 24 | $(sel).each(function () { 25 | $(this).html($this._tryTranslate($(this).html())); 26 | 27 | $(this).val($this._tryTranslate($(this).val())); 28 | $(this).attr('title', $this._tryTranslate($(this).attr('title'))); 29 | }); 30 | }, 31 | 32 | _tryTranslate: function (word) { 33 | return this._words[$.trim(word)] !== undefined ? this._words[$.trim(word)] : word; 34 | }, 35 | 36 | learn: function (wordsMap) { 37 | this._words = wordsMap; 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /src/main/resources/public/swagger/lang/zh-cn.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated": "警告:已过时", 6 | "Implementation Notes": "实现备注", 7 | "Response Class": "响应类", 8 | "Status": "状态", 9 | "Parameters": "参数", 10 | "Parameter": "参数", 11 | "Value": "值", 12 | "Description": "描述", 13 | "Parameter Type": "参数类型", 14 | "Data Type": "数据类型", 15 | "Response Messages": "响应消息", 16 | "HTTP Status Code": "HTTP状态码", 17 | "Reason": "原因", 18 | "Response Model": "响应模型", 19 | "Request URL": "请求URL", 20 | "Response Body": "响应体", 21 | "Response Code": "响应码", 22 | "Response Headers": "响应头", 23 | "Hide Response": "隐藏响应", 24 | "Headers": "头", 25 | "Try it out!": "试一下!", 26 | "Show/Hide": "显示/隐藏", 27 | "List Operations": "显示操作", 28 | "Expand Operations": "展开操作", 29 | "Raw": "原始", 30 | "can't parse JSON. Raw result": "无法解析JSON. 原始结果", 31 | "Model Schema": "模型架构", 32 | "Model": "模型", 33 | "apply": "应用", 34 | "Username": "用户名", 35 | "Password": "密码", 36 | "Terms of service": "服务条款", 37 | "Created by": "创建者", 38 | "See more at": "查看更多:", 39 | "Contact the developer": "联系开发者", 40 | "api version": "api版本", 41 | "Response Content Type": "响应Content Type", 42 | "fetching resource": "正在获取资源", 43 | "fetching resource list": "正在获取资源列表", 44 | "Explore": "浏览", 45 | "Show Swagger Petstore Example Apis": "显示 Swagger Petstore 示例 Apis", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.": "无法从服务器读取。可能没有正确设置access-control-origin。", 47 | "Please specify the protocol for": "请指定协议:", 48 | "Can't read swagger JSON from": "无法读取swagger JSON于", 49 | "Finished Loading Resource Information. Rendering Swagger UI": "已加载资源信息。正在渲染Swagger UI", 50 | "Unable to read api": "无法读取api", 51 | "from path": "从路径", 52 | "server returned": "服务器返回" 53 | }); 54 | -------------------------------------------------------------------------------- /src/main/resources/public/swagger/lib/backbone-min.js: -------------------------------------------------------------------------------- 1 | // Backbone.js 1.1.2 2 | 3 | (function (t, e) { 4 | if (typeof define === "function" && define.amd) { 5 | define(["underscore", "jquery", "exports"], function (i, r, s) { 6 | t.Backbone = e(t, s, i, r) 7 | }) 8 | } else if (typeof exports !== "undefined") { 9 | var i = require("underscore"); 10 | e(t, exports, i) 11 | } else { 12 | t.Backbone = e(t, {}, t._, t.jQuery || t.Zepto || t.ender || t.$) 13 | } 14 | })(this, function (t, e, i, r) { 15 | var s = t.Backbone; 16 | var n = []; 17 | var a = n.push; 18 | var o = n.slice; 19 | var h = n.splice; 20 | e.VERSION = "1.1.2"; 21 | e.$ = r; 22 | e.noConflict = function () { 23 | t.Backbone = s; 24 | return this 25 | }; 26 | e.emulateHTTP = false; 27 | e.emulateJSON = false; 28 | var u = e.Events = { 29 | on: function (t, e, i) { 30 | if (!c(this, "on", t, [e, i]) || !e)return this; 31 | this._events || (this._events = {}); 32 | var r = this._events[t] || (this._events[t] = []); 33 | r.push({callback: e, context: i, ctx: i || this}); 34 | return this 35 | }, once: function (t, e, r) { 36 | if (!c(this, "once", t, [e, r]) || !e)return this; 37 | var s = this; 38 | var n = i.once(function () { 39 | s.off(t, n); 40 | e.apply(this, arguments) 41 | }); 42 | n._callback = e; 43 | return this.on(t, n, r) 44 | }, off: function (t, e, r) { 45 | var s, n, a, o, h, u, l, f; 46 | if (!this._events || !c(this, "off", t, [e, r]))return this; 47 | if (!t && !e && !r) { 48 | this._events = void 0; 49 | return this 50 | } 51 | o = t ? [t] : i.keys(this._events); 52 | for (h = 0, u = o.length; h < u; h++) { 53 | t = o[h]; 54 | if (a = this._events[t]) { 55 | this._events[t] = s = []; 56 | if (e || r) { 57 | for (l = 0, f = a.length; l < f; l++) { 58 | n = a[l]; 59 | if (e && e !== n.callback && e !== n.callback._callback || r && r !== n.context) { 60 | s.push(n) 61 | } 62 | } 63 | } 64 | if (!s.length)delete this._events[t] 65 | } 66 | } 67 | return this 68 | }, trigger: function (t) { 69 | if (!this._events)return this; 70 | var e = o.call(arguments, 1); 71 | if (!c(this, "trigger", t, e))return this; 72 | var i = this._events[t]; 73 | var r = this._events.all; 74 | if (i)f(i, e); 75 | if (r)f(r, arguments); 76 | return this 77 | }, stopListening: function (t, e, r) { 78 | var s = this._listeningTo; 79 | if (!s)return this; 80 | var n = !e && !r; 81 | if (!r && typeof e === "object")r = this; 82 | if (t)(s = {})[t._listenId] = t; 83 | for (var a in s) { 84 | t = s[a]; 85 | t.off(e, r, this); 86 | if (n || i.isEmpty(t._events))delete this._listeningTo[a] 87 | } 88 | return this 89 | } 90 | }; 91 | var l = /\s+/; 92 | var c = function (t, e, i, r) { 93 | if (!i)return true; 94 | if (typeof i === "object") { 95 | for (var s in i) { 96 | t[e].apply(t, [s, i[s]].concat(r)) 97 | } 98 | return false 99 | } 100 | if (l.test(i)) { 101 | var n = i.split(l); 102 | for (var a = 0, o = n.length; a < o; a++) { 103 | t[e].apply(t, [n[a]].concat(r)) 104 | } 105 | return false 106 | } 107 | return true 108 | }; 109 | var f = function (t, e) { 110 | var i, r = -1, s = t.length, n = e[0], a = e[1], o = e[2]; 111 | switch (e.length) { 112 | case 0: 113 | while (++r < s)(i = t[r]).callback.call(i.ctx); 114 | return; 115 | case 1: 116 | while (++r < s)(i = t[r]).callback.call(i.ctx, n); 117 | return; 118 | case 2: 119 | while (++r < s)(i = t[r]).callback.call(i.ctx, n, a); 120 | return; 121 | case 3: 122 | while (++r < s)(i = t[r]).callback.call(i.ctx, n, a, o); 123 | return; 124 | default: 125 | while (++r < s)(i = t[r]).callback.apply(i.ctx, e); 126 | return 127 | } 128 | }; 129 | var d = {listenTo: "on", listenToOnce: "once"}; 130 | i.each(d, function (t, e) { 131 | u[e] = function (e, r, s) { 132 | var n = this._listeningTo || (this._listeningTo = {}); 133 | var a = e._listenId || (e._listenId = i.uniqueId("l")); 134 | n[a] = e; 135 | if (!s && typeof r === "object")s = this; 136 | e[t](r, s, this); 137 | return this 138 | } 139 | }); 140 | u.bind = u.on; 141 | u.unbind = u.off; 142 | i.extend(e, u); 143 | var p = e.Model = function (t, e) { 144 | var r = t || {}; 145 | e || (e = {}); 146 | this.cid = i.uniqueId("c"); 147 | this.attributes = {}; 148 | if (e.collection)this.collection = e.collection; 149 | if (e.parse)r = this.parse(r, e) || {}; 150 | r = i.defaults({}, r, i.result(this, "defaults")); 151 | this.set(r, e); 152 | this.changed = {}; 153 | this.initialize.apply(this, arguments) 154 | }; 155 | i.extend(p.prototype, u, { 156 | changed: null, validationError: null, idAttribute: "id", initialize: function () { 157 | }, toJSON: function (t) { 158 | return i.clone(this.attributes) 159 | }, sync: function () { 160 | return e.sync.apply(this, arguments) 161 | }, get: function (t) { 162 | return this.attributes[t] 163 | }, escape: function (t) { 164 | return i.escape(this.get(t)) 165 | }, has: function (t) { 166 | return this.get(t) != null 167 | }, set: function (t, e, r) { 168 | var s, n, a, o, h, u, l, c; 169 | if (t == null)return this; 170 | if (typeof t === "object") { 171 | n = t; 172 | r = e 173 | } else { 174 | (n = {})[t] = e 175 | } 176 | r || (r = {}); 177 | if (!this._validate(n, r))return false; 178 | a = r.unset; 179 | h = r.silent; 180 | o = []; 181 | u = this._changing; 182 | this._changing = true; 183 | if (!u) { 184 | this._previousAttributes = i.clone(this.attributes); 185 | this.changed = {} 186 | } 187 | c = this.attributes, l = this._previousAttributes; 188 | if (this.idAttribute in n)this.id = n[this.idAttribute]; 189 | for (s in n) { 190 | e = n[s]; 191 | if (!i.isEqual(c[s], e))o.push(s); 192 | if (!i.isEqual(l[s], e)) { 193 | this.changed[s] = e 194 | } else { 195 | delete this.changed[s] 196 | } 197 | a ? delete c[s] : c[s] = e 198 | } 199 | if (!h) { 200 | if (o.length)this._pending = r; 201 | for (var f = 0, d = o.length; f < d; f++) { 202 | this.trigger("change:" + o[f], this, c[o[f]], r) 203 | } 204 | } 205 | if (u)return this; 206 | if (!h) { 207 | while (this._pending) { 208 | r = this._pending; 209 | this._pending = false; 210 | this.trigger("change", this, r) 211 | } 212 | } 213 | this._pending = false; 214 | this._changing = false; 215 | return this 216 | }, unset: function (t, e) { 217 | return this.set(t, void 0, i.extend({}, e, {unset: true})) 218 | }, clear: function (t) { 219 | var e = {}; 220 | for (var r in this.attributes)e[r] = void 0; 221 | return this.set(e, i.extend({}, t, {unset: true})) 222 | }, hasChanged: function (t) { 223 | if (t == null)return !i.isEmpty(this.changed); 224 | return i.has(this.changed, t) 225 | }, changedAttributes: function (t) { 226 | if (!t)return this.hasChanged() ? i.clone(this.changed) : false; 227 | var e, r = false; 228 | var s = this._changing ? this._previousAttributes : this.attributes; 229 | for (var n in t) { 230 | if (i.isEqual(s[n], e = t[n]))continue; 231 | (r || (r = {}))[n] = e 232 | } 233 | return r 234 | }, previous: function (t) { 235 | if (t == null || !this._previousAttributes)return null; 236 | return this._previousAttributes[t] 237 | }, previousAttributes: function () { 238 | return i.clone(this._previousAttributes) 239 | }, fetch: function (t) { 240 | t = t ? i.clone(t) : {}; 241 | if (t.parse === void 0)t.parse = true; 242 | var e = this; 243 | var r = t.success; 244 | t.success = function (i) { 245 | if (!e.set(e.parse(i, t), t))return false; 246 | if (r)r(e, i, t); 247 | e.trigger("sync", e, i, t) 248 | }; 249 | q(this, t); 250 | return this.sync("read", this, t) 251 | }, save: function (t, e, r) { 252 | var s, n, a, o = this.attributes; 253 | if (t == null || typeof t === "object") { 254 | s = t; 255 | r = e 256 | } else { 257 | (s = {})[t] = e 258 | } 259 | r = i.extend({validate: true}, r); 260 | if (s && !r.wait) { 261 | if (!this.set(s, r))return false 262 | } else { 263 | if (!this._validate(s, r))return false 264 | } 265 | if (s && r.wait) { 266 | this.attributes = i.extend({}, o, s) 267 | } 268 | if (r.parse === void 0)r.parse = true; 269 | var h = this; 270 | var u = r.success; 271 | r.success = function (t) { 272 | h.attributes = o; 273 | var e = h.parse(t, r); 274 | if (r.wait)e = i.extend(s || {}, e); 275 | if (i.isObject(e) && !h.set(e, r)) { 276 | return false 277 | } 278 | if (u)u(h, t, r); 279 | h.trigger("sync", h, t, r) 280 | }; 281 | q(this, r); 282 | n = this.isNew() ? "create" : r.patch ? "patch" : "update"; 283 | if (n === "patch")r.attrs = s; 284 | a = this.sync(n, this, r); 285 | if (s && r.wait)this.attributes = o; 286 | return a 287 | }, destroy: function (t) { 288 | t = t ? i.clone(t) : {}; 289 | var e = this; 290 | var r = t.success; 291 | var s = function () { 292 | e.trigger("destroy", e, e.collection, t) 293 | }; 294 | t.success = function (i) { 295 | if (t.wait || e.isNew())s(); 296 | if (r)r(e, i, t); 297 | if (!e.isNew())e.trigger("sync", e, i, t) 298 | }; 299 | if (this.isNew()) { 300 | t.success(); 301 | return false 302 | } 303 | q(this, t); 304 | var n = this.sync("delete", this, t); 305 | if (!t.wait)s(); 306 | return n 307 | }, url: function () { 308 | var t = i.result(this, "urlRoot") || i.result(this.collection, "url") || M(); 309 | if (this.isNew())return t; 310 | return t.replace(/([^\/])$/, "$1/") + encodeURIComponent(this.id) 311 | }, parse: function (t, e) { 312 | return t 313 | }, clone: function () { 314 | return new this.constructor(this.attributes) 315 | }, isNew: function () { 316 | return !this.has(this.idAttribute) 317 | }, isValid: function (t) { 318 | return this._validate({}, i.extend(t || {}, {validate: true})) 319 | }, _validate: function (t, e) { 320 | if (!e.validate || !this.validate)return true; 321 | t = i.extend({}, this.attributes, t); 322 | var r = this.validationError = this.validate(t, e) || null; 323 | if (!r)return true; 324 | this.trigger("invalid", this, r, i.extend(e, {validationError: r})); 325 | return false 326 | } 327 | }); 328 | var v = ["keys", "values", "pairs", "invert", "pick", "omit"]; 329 | i.each(v, function (t) { 330 | p.prototype[t] = function () { 331 | var e = o.call(arguments); 332 | e.unshift(this.attributes); 333 | return i[t].apply(i, e) 334 | } 335 | }); 336 | var g = e.Collection = function (t, e) { 337 | e || (e = {}); 338 | if (e.model)this.model = e.model; 339 | if (e.comparator !== void 0)this.comparator = e.comparator; 340 | this._reset(); 341 | this.initialize.apply(this, arguments); 342 | if (t)this.reset(t, i.extend({silent: true}, e)) 343 | }; 344 | var m = {add: true, remove: true, merge: true}; 345 | var y = {add: true, remove: false}; 346 | i.extend(g.prototype, u, { 347 | model: p, initialize: function () { 348 | }, toJSON: function (t) { 349 | return this.map(function (e) { 350 | return e.toJSON(t) 351 | }) 352 | }, sync: function () { 353 | return e.sync.apply(this, arguments) 354 | }, add: function (t, e) { 355 | return this.set(t, i.extend({merge: false}, e, y)) 356 | }, remove: function (t, e) { 357 | var r = !i.isArray(t); 358 | t = r ? [t] : i.clone(t); 359 | e || (e = {}); 360 | var s, n, a, o; 361 | for (s = 0, n = t.length; s < n; s++) { 362 | o = t[s] = this.get(t[s]); 363 | if (!o)continue; 364 | delete this._byId[o.id]; 365 | delete this._byId[o.cid]; 366 | a = this.indexOf(o); 367 | this.models.splice(a, 1); 368 | this.length--; 369 | if (!e.silent) { 370 | e.index = a; 371 | o.trigger("remove", o, this, e) 372 | } 373 | this._removeReference(o, e) 374 | } 375 | return r ? t[0] : t 376 | }, set: function (t, e) { 377 | e = i.defaults({}, e, m); 378 | if (e.parse)t = this.parse(t, e); 379 | var r = !i.isArray(t); 380 | t = r ? t ? [t] : [] : i.clone(t); 381 | var s, n, a, o, h, u, l; 382 | var c = e.at; 383 | var f = this.model; 384 | var d = this.comparator && c == null && e.sort !== false; 385 | var v = i.isString(this.comparator) ? this.comparator : null; 386 | var g = [], y = [], _ = {}; 387 | var b = e.add, w = e.merge, x = e.remove; 388 | var E = !d && b && x ? [] : false; 389 | for (s = 0, n = t.length; s < n; s++) { 390 | h = t[s] || {}; 391 | if (h instanceof p) { 392 | a = o = h 393 | } else { 394 | a = h[f.prototype.idAttribute || "id"] 395 | } 396 | if (u = this.get(a)) { 397 | if (x)_[u.cid] = true; 398 | if (w) { 399 | h = h === o ? o.attributes : h; 400 | if (e.parse)h = u.parse(h, e); 401 | u.set(h, e); 402 | if (d && !l && u.hasChanged(v))l = true 403 | } 404 | t[s] = u 405 | } else if (b) { 406 | o = t[s] = this._prepareModel(h, e); 407 | if (!o)continue; 408 | g.push(o); 409 | this._addReference(o, e) 410 | } 411 | o = u || o; 412 | if (E && (o.isNew() || !_[o.id]))E.push(o); 413 | _[o.id] = true 414 | } 415 | if (x) { 416 | for (s = 0, n = this.length; s < n; ++s) { 417 | if (!_[(o = this.models[s]).cid])y.push(o) 418 | } 419 | if (y.length)this.remove(y, e) 420 | } 421 | if (g.length || E && E.length) { 422 | if (d)l = true; 423 | this.length += g.length; 424 | if (c != null) { 425 | for (s = 0, n = g.length; s < n; s++) { 426 | this.models.splice(c + s, 0, g[s]) 427 | } 428 | } else { 429 | if (E)this.models.length = 0; 430 | var k = E || g; 431 | for (s = 0, n = k.length; s < n; s++) { 432 | this.models.push(k[s]) 433 | } 434 | } 435 | } 436 | if (l)this.sort({silent: true}); 437 | if (!e.silent) { 438 | for (s = 0, n = g.length; s < n; s++) { 439 | (o = g[s]).trigger("add", o, this, e) 440 | } 441 | if (l || E && E.length)this.trigger("sort", this, e) 442 | } 443 | return r ? t[0] : t 444 | }, reset: function (t, e) { 445 | e || (e = {}); 446 | for (var r = 0, s = this.models.length; r < s; r++) { 447 | this._removeReference(this.models[r], e) 448 | } 449 | e.previousModels = this.models; 450 | this._reset(); 451 | t = this.add(t, i.extend({silent: true}, e)); 452 | if (!e.silent)this.trigger("reset", this, e); 453 | return t 454 | }, push: function (t, e) { 455 | return this.add(t, i.extend({at: this.length}, e)) 456 | }, pop: function (t) { 457 | var e = this.at(this.length - 1); 458 | this.remove(e, t); 459 | return e 460 | }, unshift: function (t, e) { 461 | return this.add(t, i.extend({at: 0}, e)) 462 | }, shift: function (t) { 463 | var e = this.at(0); 464 | this.remove(e, t); 465 | return e 466 | }, slice: function () { 467 | return o.apply(this.models, arguments) 468 | }, get: function (t) { 469 | if (t == null)return void 0; 470 | return this._byId[t] || this._byId[t.id] || this._byId[t.cid] 471 | }, at: function (t) { 472 | return this.models[t] 473 | }, where: function (t, e) { 474 | if (i.isEmpty(t))return e ? void 0 : []; 475 | return this[e ? "find" : "filter"](function (e) { 476 | for (var i in t) { 477 | if (t[i] !== e.get(i))return false 478 | } 479 | return true 480 | }) 481 | }, findWhere: function (t) { 482 | return this.where(t, true) 483 | }, sort: function (t) { 484 | if (!this.comparator)throw new Error("Cannot sort a set without a comparator"); 485 | t || (t = {}); 486 | if (i.isString(this.comparator) || this.comparator.length === 1) { 487 | this.models = this.sortBy(this.comparator, this) 488 | } else { 489 | this.models.sort(i.bind(this.comparator, this)) 490 | } 491 | if (!t.silent)this.trigger("sort", this, t); 492 | return this 493 | }, pluck: function (t) { 494 | return i.invoke(this.models, "get", t) 495 | }, fetch: function (t) { 496 | t = t ? i.clone(t) : {}; 497 | if (t.parse === void 0)t.parse = true; 498 | var e = t.success; 499 | var r = this; 500 | t.success = function (i) { 501 | var s = t.reset ? "reset" : "set"; 502 | r[s](i, t); 503 | if (e)e(r, i, t); 504 | r.trigger("sync", r, i, t) 505 | }; 506 | q(this, t); 507 | return this.sync("read", this, t) 508 | }, create: function (t, e) { 509 | e = e ? i.clone(e) : {}; 510 | if (!(t = this._prepareModel(t, e)))return false; 511 | if (!e.wait)this.add(t, e); 512 | var r = this; 513 | var s = e.success; 514 | e.success = function (t, i) { 515 | if (e.wait)r.add(t, e); 516 | if (s)s(t, i, e) 517 | }; 518 | t.save(null, e); 519 | return t 520 | }, parse: function (t, e) { 521 | return t 522 | }, clone: function () { 523 | return new this.constructor(this.models) 524 | }, _reset: function () { 525 | this.length = 0; 526 | this.models = []; 527 | this._byId = {} 528 | }, _prepareModel: function (t, e) { 529 | if (t instanceof p)return t; 530 | e = e ? i.clone(e) : {}; 531 | e.collection = this; 532 | var r = new this.model(t, e); 533 | if (!r.validationError)return r; 534 | this.trigger("invalid", this, r.validationError, e); 535 | return false 536 | }, _addReference: function (t, e) { 537 | this._byId[t.cid] = t; 538 | if (t.id != null)this._byId[t.id] = t; 539 | if (!t.collection)t.collection = this; 540 | t.on("all", this._onModelEvent, this) 541 | }, _removeReference: function (t, e) { 542 | if (this === t.collection)delete t.collection; 543 | t.off("all", this._onModelEvent, this) 544 | }, _onModelEvent: function (t, e, i, r) { 545 | if ((t === "add" || t === "remove") && i !== this)return; 546 | if (t === "destroy")this.remove(e, r); 547 | if (e && t === "change:" + e.idAttribute) { 548 | delete this._byId[e.previous(e.idAttribute)]; 549 | if (e.id != null)this._byId[e.id] = e 550 | } 551 | this.trigger.apply(this, arguments) 552 | } 553 | }); 554 | var _ = ["forEach", "each", "map", "collect", "reduce", "foldl", "inject", "reduceRight", "foldr", "find", "detect", "filter", "select", "reject", "every", "all", "some", "any", "include", "contains", "invoke", "max", "min", "toArray", "size", "first", "head", "take", "initial", "rest", "tail", "drop", "last", "without", "difference", "indexOf", "shuffle", "lastIndexOf", "isEmpty", "chain", "sample"]; 555 | i.each(_, function (t) { 556 | g.prototype[t] = function () { 557 | var e = o.call(arguments); 558 | e.unshift(this.models); 559 | return i[t].apply(i, e) 560 | } 561 | }); 562 | var b = ["groupBy", "countBy", "sortBy", "indexBy"]; 563 | i.each(b, function (t) { 564 | g.prototype[t] = function (e, r) { 565 | var s = i.isFunction(e) ? e : function (t) { 566 | return t.get(e) 567 | }; 568 | return i[t](this.models, s, r) 569 | } 570 | }); 571 | var w = e.View = function (t) { 572 | this.cid = i.uniqueId("view"); 573 | t || (t = {}); 574 | i.extend(this, i.pick(t, E)); 575 | this._ensureElement(); 576 | this.initialize.apply(this, arguments); 577 | this.delegateEvents() 578 | }; 579 | var x = /^(\S+)\s*(.*)$/; 580 | var E = ["model", "collection", "el", "id", "attributes", "className", "tagName", "events"]; 581 | i.extend(w.prototype, u, { 582 | tagName: "div", $: function (t) { 583 | return this.$el.find(t) 584 | }, initialize: function () { 585 | }, render: function () { 586 | return this 587 | }, remove: function () { 588 | this.$el.remove(); 589 | this.stopListening(); 590 | return this 591 | }, setElement: function (t, i) { 592 | if (this.$el)this.undelegateEvents(); 593 | this.$el = t instanceof e.$ ? t : e.$(t); 594 | this.el = this.$el[0]; 595 | if (i !== false)this.delegateEvents(); 596 | return this 597 | }, delegateEvents: function (t) { 598 | if (!(t || (t = i.result(this, "events"))))return this; 599 | this.undelegateEvents(); 600 | for (var e in t) { 601 | var r = t[e]; 602 | if (!i.isFunction(r))r = this[t[e]]; 603 | if (!r)continue; 604 | var s = e.match(x); 605 | var n = s[1], a = s[2]; 606 | r = i.bind(r, this); 607 | n += ".delegateEvents" + this.cid; 608 | if (a === "") { 609 | this.$el.on(n, r) 610 | } else { 611 | this.$el.on(n, a, r) 612 | } 613 | } 614 | return this 615 | }, undelegateEvents: function () { 616 | this.$el.off(".delegateEvents" + this.cid); 617 | return this 618 | }, _ensureElement: function () { 619 | if (!this.el) { 620 | var t = i.extend({}, i.result(this, "attributes")); 621 | if (this.id)t.id = i.result(this, "id"); 622 | if (this.className)t["class"] = i.result(this, "className"); 623 | var r = e.$("<" + i.result(this, "tagName") + ">").attr(t); 624 | this.setElement(r, false) 625 | } else { 626 | this.setElement(i.result(this, "el"), false) 627 | } 628 | } 629 | }); 630 | e.sync = function (t, r, s) { 631 | var n = T[t]; 632 | i.defaults(s || (s = {}), {emulateHTTP: e.emulateHTTP, emulateJSON: e.emulateJSON}); 633 | var a = {type: n, dataType: "json"}; 634 | if (!s.url) { 635 | a.url = i.result(r, "url") || M() 636 | } 637 | if (s.data == null && r && (t === "create" || t === "update" || t === "patch")) { 638 | a.contentType = "application/json"; 639 | a.data = JSON.stringify(s.attrs || r.toJSON(s)) 640 | } 641 | if (s.emulateJSON) { 642 | a.contentType = "application/x-www-form-urlencoded"; 643 | a.data = a.data ? {model: a.data} : {} 644 | } 645 | if (s.emulateHTTP && (n === "PUT" || n === "DELETE" || n === "PATCH")) { 646 | a.type = "POST"; 647 | if (s.emulateJSON)a.data._method = n; 648 | var o = s.beforeSend; 649 | s.beforeSend = function (t) { 650 | t.setRequestHeader("X-HTTP-Method-Override", n); 651 | if (o)return o.apply(this, arguments) 652 | } 653 | } 654 | if (a.type !== "GET" && !s.emulateJSON) { 655 | a.processData = false 656 | } 657 | if (a.type === "PATCH" && k) { 658 | a.xhr = function () { 659 | return new ActiveXObject("Microsoft.XMLHTTP") 660 | } 661 | } 662 | var h = s.xhr = e.ajax(i.extend(a, s)); 663 | r.trigger("request", r, h, s); 664 | return h 665 | }; 666 | var k = typeof window !== "undefined" && !!window.ActiveXObject && !(window.XMLHttpRequest && (new XMLHttpRequest).dispatchEvent); 667 | var T = {create: "POST", update: "PUT", patch: "PATCH", "delete": "DELETE", read: "GET"}; 668 | e.ajax = function () { 669 | return e.$.ajax.apply(e.$, arguments) 670 | }; 671 | var $ = e.Router = function (t) { 672 | t || (t = {}); 673 | if (t.routes)this.routes = t.routes; 674 | this._bindRoutes(); 675 | this.initialize.apply(this, arguments) 676 | }; 677 | var S = /\((.*?)\)/g; 678 | var H = /(\(\?)?:\w+/g; 679 | var A = /\*\w+/g; 680 | var I = /[\-{}\[\]+?.,\\\^$|#\s]/g; 681 | i.extend($.prototype, u, { 682 | initialize: function () { 683 | }, route: function (t, r, s) { 684 | if (!i.isRegExp(t))t = this._routeToRegExp(t); 685 | if (i.isFunction(r)) { 686 | s = r; 687 | r = "" 688 | } 689 | if (!s)s = this[r]; 690 | var n = this; 691 | e.history.route(t, function (i) { 692 | var a = n._extractParameters(t, i); 693 | n.execute(s, a); 694 | n.trigger.apply(n, ["route:" + r].concat(a)); 695 | n.trigger("route", r, a); 696 | e.history.trigger("route", n, r, a) 697 | }); 698 | return this 699 | }, execute: function (t, e) { 700 | if (t)t.apply(this, e) 701 | }, navigate: function (t, i) { 702 | e.history.navigate(t, i); 703 | return this 704 | }, _bindRoutes: function () { 705 | if (!this.routes)return; 706 | this.routes = i.result(this, "routes"); 707 | var t, e = i.keys(this.routes); 708 | while ((t = e.pop()) != null) { 709 | this.route(t, this.routes[t]) 710 | } 711 | }, _routeToRegExp: function (t) { 712 | t = t.replace(I, "\\$&").replace(S, "(?:$1)?").replace(H, function (t, e) { 713 | return e ? t : "([^/?]+)" 714 | }).replace(A, "([^?]*?)"); 715 | return new RegExp("^" + t + "(?:\\?([\\s\\S]*))?$") 716 | }, _extractParameters: function (t, e) { 717 | var r = t.exec(e).slice(1); 718 | return i.map(r, function (t, e) { 719 | if (e === r.length - 1)return t || null; 720 | return t ? decodeURIComponent(t) : null 721 | }) 722 | } 723 | }); 724 | var N = e.History = function () { 725 | this.handlers = []; 726 | i.bindAll(this, "checkUrl"); 727 | if (typeof window !== "undefined") { 728 | this.location = window.location; 729 | this.history = window.history 730 | } 731 | }; 732 | var R = /^[#\/]|\s+$/g; 733 | var O = /^\/+|\/+$/g; 734 | var P = /msie [\w.]+/; 735 | var C = /\/$/; 736 | var j = /#.*$/; 737 | N.started = false; 738 | i.extend(N.prototype, u, { 739 | interval: 50, atRoot: function () { 740 | return this.location.pathname.replace(/[^\/]$/, "$&/") === this.root 741 | }, getHash: function (t) { 742 | var e = (t || this).location.href.match(/#(.*)$/); 743 | return e ? e[1] : "" 744 | }, getFragment: function (t, e) { 745 | if (t == null) { 746 | if (this._hasPushState || !this._wantsHashChange || e) { 747 | t = decodeURI(this.location.pathname + this.location.search); 748 | var i = this.root.replace(C, ""); 749 | if (!t.indexOf(i))t = t.slice(i.length) 750 | } else { 751 | t = this.getHash() 752 | } 753 | } 754 | return t.replace(R, "") 755 | }, start: function (t) { 756 | if (N.started)throw new Error("Backbone.history has already been started"); 757 | N.started = true; 758 | this.options = i.extend({root: "/"}, this.options, t); 759 | this.root = this.options.root; 760 | this._wantsHashChange = this.options.hashChange !== false; 761 | this._wantsPushState = !!this.options.pushState; 762 | this._hasPushState = !!(this.options.pushState && this.history && this.history.pushState); 763 | var r = this.getFragment(); 764 | var s = document.documentMode; 765 | var n = P.exec(navigator.userAgent.toLowerCase()) && (!s || s <= 7); 766 | this.root = ("/" + this.root + "/").replace(O, "/"); 767 | if (n && this._wantsHashChange) { 768 | var a = e.$('