mirror of https://github.com/Squidex/squidex.git
198 changed files with 7395 additions and 66 deletions
@ -0,0 +1,4 @@ |
|||
fromCategory('pinkparrot') |
|||
.whenAny(function(s,e) { |
|||
linkTo('pinkparrot',e); |
|||
}); |
|||
@ -0,0 +1,33 @@ |
|||
// ==========================================================================
|
|||
// WebpackUsage.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using Microsoft.AspNetCore.Builder; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using PinkParrot.Pipeline; |
|||
|
|||
namespace PinkParrot.Configurations |
|||
{ |
|||
public static class WebpackExtensions |
|||
{ |
|||
public static IServiceCollection AddWebpack(this IServiceCollection services) |
|||
{ |
|||
services.AddSingleton<WebpackRunner>(); |
|||
|
|||
return services; |
|||
} |
|||
|
|||
public static IApplicationBuilder UseWebpack(this IApplicationBuilder app) |
|||
{ |
|||
app.ApplicationServices.GetService<WebpackRunner>().Execute(); |
|||
|
|||
app.UseMiddleware<WebpackMiddleware>(); |
|||
|
|||
return app; |
|||
} |
|||
} |
|||
} |
|||
@ -1,31 +1,54 @@ |
|||
using System; |
|||
// ==========================================================================
|
|||
// AppController.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using PinkParrot.Infrastructure.CQRS.Commands; |
|||
using PinkParrot.Infrastructure.Reflection; |
|||
using PinkParrot.Modules.Api.Apps.Models; |
|||
using PinkParrot.Modules.Api.Schemas.Models; |
|||
using PinkParrot.Pipeline; |
|||
using PinkParrot.Read.Apps.Repositories; |
|||
using PinkParrot.Write.Apps.Commands; |
|||
|
|||
namespace PinkParrot.Modules.Api.Apps |
|||
{ |
|||
public class AppController |
|||
[DeactivateForAppDomain] |
|||
public class AppController : ControllerBase |
|||
{ |
|||
private readonly IAppRepository appRepository; |
|||
|
|||
public AppController(IAppRepository appRepository) |
|||
public AppController(ICommandBus commandBus, IAppRepository appRepository) |
|||
: base(commandBus) |
|||
{ |
|||
this.appRepository = appRepository; |
|||
} |
|||
|
|||
[HttpGet] |
|||
[Route("api/schemas/")] |
|||
[Route("api/apps/")] |
|||
public async Task<List<ListAppDto>> Query() |
|||
{ |
|||
var schemas = await appRepository.QueryAllAsync(); |
|||
|
|||
return schemas.Select(s => SimpleMapper.Map(s, new ListAppDto())).ToList(); |
|||
} |
|||
|
|||
[HttpPost] |
|||
[Route("api/apps/")] |
|||
public async Task<IActionResult> Create([FromBody] CreateAppDto model) |
|||
{ |
|||
var command = SimpleMapper.Map(model, new CreateApp { AggregateId = Guid.NewGuid() }); |
|||
|
|||
await CommandBus.PublishAsync(command); |
|||
|
|||
return CreatedAtAction("Query", new EntityCreatedDto { Id = command.AggregateId }); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,15 @@ |
|||
// ==========================================================================
|
|||
// CreateAppDto.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
namespace PinkParrot.Modules.Api.Apps.Models |
|||
{ |
|||
public sealed class CreateAppDto |
|||
{ |
|||
public string Name { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
// ==========================================================================
|
|||
// DeactivateForAppDomainAttribute.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.AspNetCore.Mvc.Filters; |
|||
|
|||
namespace PinkParrot.Pipeline |
|||
{ |
|||
public sealed class DeactivateForAppDomainAttribute : ActionFilterAttribute |
|||
{ |
|||
public override void OnActionExecuting(ActionExecutingContext context) |
|||
{ |
|||
var app = context.HttpContext.Features.Get<IAppFeature>(); |
|||
|
|||
if (app != null) |
|||
{ |
|||
context.Result = new NotFoundResult(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,129 @@ |
|||
// ==========================================================================
|
|||
// WebpackMiddleware.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.IO; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Microsoft.Extensions.Logging; |
|||
|
|||
// ReSharper disable LoopCanBeConvertedToQuery
|
|||
|
|||
namespace PinkParrot.Pipeline |
|||
{ |
|||
public sealed class WebpackMiddleware |
|||
{ |
|||
private const string Host = "localhost"; |
|||
private const string Port = "3000"; |
|||
private static readonly string[] Scripts = { "polyfills.js", "vendor.js", "app.js" }; |
|||
private static readonly string[] Styles = { "vendor.css" }; |
|||
private readonly RequestDelegate next; |
|||
private readonly ILogger logger; |
|||
|
|||
public WebpackMiddleware(RequestDelegate next, ILoggerFactory loggerFactory) |
|||
{ |
|||
logger = loggerFactory.CreateLogger<WebpackMiddleware>(); |
|||
|
|||
this.next = next; |
|||
} |
|||
|
|||
public async Task Invoke(HttpContext context) |
|||
{ |
|||
var buffer = new MemoryStream(); |
|||
var body = context.Response.Body; |
|||
|
|||
context.Response.Body = buffer; |
|||
|
|||
await next(context); |
|||
|
|||
buffer.Seek(0, SeekOrigin.Begin); |
|||
|
|||
if (context.Response.StatusCode == 200 && IsHtml(context)) |
|||
{ |
|||
using (var reader = new StreamReader(buffer)) |
|||
{ |
|||
var response = await reader.ReadToEndAsync(); |
|||
|
|||
response = InjectStyles(response); |
|||
response = InjectScripts(response); |
|||
|
|||
using (var memoryStream = new MemoryStream()) |
|||
{ |
|||
using (var writer = new StreamWriter(memoryStream)) |
|||
{ |
|||
writer.Write(response); |
|||
writer.Flush(); |
|||
|
|||
memoryStream.Seek(0, SeekOrigin.Begin); |
|||
|
|||
context.Response.Headers["Content-Length"] = memoryStream.Length.ToString(); |
|||
|
|||
await memoryStream.CopyToAsync(body); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
await buffer.CopyToAsync(body); |
|||
} |
|||
|
|||
context.Response.Body = body; |
|||
} |
|||
|
|||
private string InjectStyles(string response) |
|||
{ |
|||
if (!response.Contains("</head>")) |
|||
{ |
|||
return response; |
|||
} |
|||
|
|||
logger.LogInformation("A full html page is returned so the necessary styles for webpack will be injected"); |
|||
|
|||
var stylesTag = string.Empty; |
|||
|
|||
foreach (var file in Styles) |
|||
{ |
|||
stylesTag += $"<link href=\"http://{Host}:{Port}/{file}\" rel=\"stylesheet\" >";
|
|||
} |
|||
|
|||
response = response.Replace("</head>", $"{stylesTag}</head>"); |
|||
|
|||
logger.LogInformation($"Inject style {stylesTag} as a last element in the head "); |
|||
|
|||
return response; |
|||
} |
|||
|
|||
private string InjectScripts(string response) |
|||
{ |
|||
if (!response.Contains("</body>")) |
|||
{ |
|||
return response; |
|||
} |
|||
|
|||
logger.LogInformation("A full html page is returned so the necessary script for webpack will be injected"); |
|||
|
|||
var scriptsTag = string.Empty; |
|||
|
|||
foreach (var file in Scripts) |
|||
{ |
|||
scriptsTag += $"<script type=\"text/javascript\" src=\"http://{Host}:{Port}/{file}\"></script>"; |
|||
} |
|||
|
|||
response = response.Replace("</body>", $"{scriptsTag}</body>"); |
|||
|
|||
logger.LogInformation($"Inject script {scriptsTag} as a last element in the body "); |
|||
|
|||
return response; |
|||
} |
|||
|
|||
private static bool IsHtml(HttpContext context) |
|||
{ |
|||
return context.Response.ContentType?.ToLower().Contains("text/html") == true; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,93 @@ |
|||
// ==========================================================================
|
|||
// WebpackRunner.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Diagnostics; |
|||
using System.IO; |
|||
using Microsoft.AspNetCore.Hosting; |
|||
using Microsoft.Extensions.Logging; |
|||
|
|||
// ReSharper disable ConvertToConstant.Local
|
|||
|
|||
namespace PinkParrot.Pipeline |
|||
{ |
|||
public sealed class WebpackRunner |
|||
{ |
|||
private const string WebpackDevServer = "webpack-dev-server"; |
|||
|
|||
private readonly ILoggerFactory loggerFactory; |
|||
private readonly IApplicationLifetime lifetime; |
|||
private Process process; |
|||
|
|||
public WebpackRunner(ILoggerFactory loggerFactory, IApplicationLifetime lifetime) |
|||
{ |
|||
this.loggerFactory = loggerFactory; |
|||
|
|||
this.lifetime = lifetime; |
|||
} |
|||
|
|||
public void Execute() |
|||
{ |
|||
if (process != null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var logger = loggerFactory.CreateLogger(WebpackDevServer); |
|||
|
|||
EnsuereNodeModluesInstalled(logger); |
|||
|
|||
logger.LogInformation($"{WebpackDevServer} Execution started"); |
|||
|
|||
var app = GetNodeExecutable(WebpackDevServer); |
|||
var args = "--inline --hot --port 3000"; |
|||
|
|||
process = Process.Start(new ProcessStartInfo |
|||
{ |
|||
FileName = app, Arguments = args, UseShellExecute = false |
|||
}); |
|||
|
|||
lifetime.ApplicationStopping.Register(OnShutdown); |
|||
|
|||
logger.LogInformation($"{WebpackDevServer} started successfully"); |
|||
} |
|||
|
|||
private void OnShutdown() |
|||
{ |
|||
process?.Kill(); |
|||
process = null; |
|||
} |
|||
|
|||
private static void EnsuereNodeModluesInstalled(ILogger logger) |
|||
{ |
|||
logger.LogInformation("Verifying required tools are installed"); |
|||
|
|||
if (!File.Exists(GetNodeExecutable(WebpackDevServer))) |
|||
{ |
|||
logger.LogError("webpack-dev-server is not installed. Please install it by executing npm i webpack-dev-server"); |
|||
} |
|||
|
|||
logger.LogInformation("All node modules are properly installed"); |
|||
} |
|||
|
|||
private static string GetNodeExecutable(string module) |
|||
{ |
|||
var executablePath = Path.Combine(Directory.GetCurrentDirectory(), "node_modules", ".bin", module); |
|||
|
|||
var osEnVariable = Environment.GetEnvironmentVariable("OS"); |
|||
|
|||
if (!string.IsNullOrEmpty(osEnVariable) && |
|||
string.Equals(osEnVariable, "Windows_NT", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
executablePath += ".cmd"; |
|||
} |
|||
|
|||
return executablePath; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,67 @@ |
|||
'use strict'; |
|||
|
|||
var path = require('path'), |
|||
fs = require('fs'), |
|||
loaderUtils = require('loader-utils'), |
|||
SourceMap = require('source-map'); |
|||
|
|||
function capitalize(str) { |
|||
return str.charAt(0).toUpperCase() + str.slice(1); |
|||
}; |
|||
|
|||
function applyPlaceholders(str, dirname, filename) { |
|||
if (!str.length) { |
|||
return str; |
|||
} |
|||
|
|||
return str |
|||
.split('[file]').join(filename) |
|||
.split('[File]').join(capitalize(filename)); |
|||
}; |
|||
|
|||
function loadBaggage(source, sourcemap) { |
|||
var query = loaderUtils.parseQuery(this.query); |
|||
|
|||
var srcFilepath = this.resourcePath; |
|||
var srcFilename = path.basename(srcFilepath, path.extname(srcFilepath)); |
|||
var srcDirpath = path.dirname(srcFilepath); |
|||
var srcDirname = srcDirpath.split(path.sep).pop(); |
|||
|
|||
this.cacheable(); |
|||
|
|||
if (Object.keys(query).length) { |
|||
var inject = '\n/* injects from baggage-loader */\n'; |
|||
|
|||
Object.keys(query).forEach(function (baggageFile) { |
|||
var baggageVar = query[baggageFile]; |
|||
|
|||
if (typeof baggageVar === 'string' || baggageVar === true) { |
|||
baggageFile = applyPlaceholders(baggageFile, srcDirname, srcFilename); |
|||
|
|||
try { |
|||
var stats = fs.statSync(path.resolve(srcDirpath, baggageFile)); |
|||
|
|||
if (stats.isFile()) { |
|||
if (baggageVar.length) { |
|||
inject += 'const ' + baggageVar + ' = '; |
|||
} |
|||
|
|||
if (baggageVar === 'styles') { |
|||
inject += '[require(\'./' + baggageFile + '\')];\n'; |
|||
} else { |
|||
inject += 'require(\'./' + baggageFile + '\');\n'; |
|||
} |
|||
} |
|||
} catch (e) { } |
|||
} |
|||
}); |
|||
|
|||
inject += '\n'; |
|||
|
|||
return inject + source; |
|||
} |
|||
|
|||
return source; |
|||
}; |
|||
|
|||
module.exports = loadBaggage; |
|||
@ -0,0 +1,47 @@ |
|||
function fixCoverage(contents) { |
|||
this.cacheable(); |
|||
|
|||
var ignores = [ |
|||
{ name: 'arguments', line: 'var _a' }, |
|||
{ name: 'decorate', line: 'var __decorate =', }, |
|||
{ name: 'metadata', line: 'var __metadata =', }, |
|||
{ name: 'extends', line: 'var __extends =', }, |
|||
{ name: 'export', line: 'function __export' } |
|||
]; |
|||
|
|||
var updates = 0; |
|||
var rows = contents.split('\n'); |
|||
|
|||
for (var rowIndex = 0; rowIndex < rows.length; rowIndex++) { |
|||
var row = rows[rowIndex].trim(); |
|||
|
|||
for (var ignoreIndex = 0; ignoreIndex < ignores.length; ignoreIndex++) { |
|||
var ignore = ignores[ignoreIndex]; |
|||
|
|||
if (row.indexOf(ignore.line) >= 0) { |
|||
rows.splice(rowIndex, 0, '/* istanbul ignore next: TypeScript ' + ignore.name + ' */'); |
|||
rowIndex++; |
|||
updates++; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (row.indexOf('hasOwnProperty') >= 0) { |
|||
rows.splice(rowIndex, 0, '/* istanbul ignore else */'); |
|||
rowIndex++; |
|||
updates++; |
|||
} |
|||
|
|||
if (updates === ignores.length) { |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (updates > 0) { |
|||
return rows.join('\n'); |
|||
} else { |
|||
return contents; |
|||
} |
|||
} |
|||
|
|||
module.exports = fixCoverage; |
|||
@ -0,0 +1,13 @@ |
|||
// ReSharper disable InconsistentNaming
|
|||
// ReSharper disable PossiblyUnassignedProperty
|
|||
// ReSharper disable InconsistentNaming
|
|||
|
|||
var path = require('path'); |
|||
|
|||
var appRoot = path.resolve(__dirname, '..'); |
|||
|
|||
exports.root = function () { |
|||
var newArgs = Array.prototype.slice.call(arguments, 0); |
|||
|
|||
return path.join.apply(path, [appRoot].concat(newArgs)); |
|||
}; |
|||
@ -0,0 +1,36 @@ |
|||
Error.stackTraceLimit = Infinity; |
|||
|
|||
require('core-js/es6'); |
|||
require('core-js/es7/reflect'); |
|||
|
|||
require('zone.js/dist/zone'); |
|||
require('zone.js/dist/long-stack-trace-zone'); |
|||
require('zone.js/dist/proxy'); |
|||
require('zone.js/dist/sync-test'); |
|||
require('zone.js/dist/jasmine-patch'); |
|||
require('zone.js/dist/async-test'); |
|||
require('zone.js/dist/fake-async-test'); |
|||
|
|||
require('rxjs/Rx'); |
|||
|
|||
var testing = require('@angular/core/testing'); |
|||
var browser = require('@angular/platform-browser-dynamic/testing'); |
|||
|
|||
testing.TestBed.initTestEnvironment( |
|||
browser.BrowserDynamicTestingModule, |
|||
browser.platformBrowserDynamicTesting() |
|||
); |
|||
|
|||
var testContext = require.context('../app', true, /\.spec\.ts/); |
|||
|
|||
/* |
|||
* get all the files, for each file, call the context function |
|||
* that will require the file and load it up here. Context will |
|||
* loop and require those spec files here |
|||
*/ |
|||
function requireAll(requireContext) { |
|||
return requireContext.keys().map(requireContext); |
|||
} |
|||
|
|||
// requires and returns all modules that match
|
|||
var modules = requireAll(testContext); |
|||
@ -0,0 +1,52 @@ |
|||
var webpackConfig = require('./webpack.test'); |
|||
|
|||
module.exports = function (config) { |
|||
var _config = { |
|||
/** |
|||
* Base path that will be used to resolve all patterns (e.g. files, exclude) |
|||
*/ |
|||
basePath: '', |
|||
|
|||
frameworks: ['jasmine'], |
|||
|
|||
/** |
|||
* Load additional test shim to setup angular2 for testing |
|||
*/ |
|||
files: [ |
|||
{ pattern: './app-config/karma-test-shim.js', watched: false } |
|||
], |
|||
|
|||
preprocessors: { |
|||
'./app-config/karma-test-shim.js': ['webpack', 'sourcemap'], |
|||
}, |
|||
|
|||
/** |
|||
* Load the files with webpack and use test configuration for it. |
|||
*/ |
|||
webpack: webpackConfig, |
|||
|
|||
webpackMiddleware: { |
|||
stats: 'errors-only' |
|||
}, |
|||
|
|||
webpackServer: { |
|||
noInfo: true |
|||
}, |
|||
|
|||
|
|||
/* |
|||
* Use a mocha style console reporter, html reporter and the code coverage reporter |
|||
*/ |
|||
reporters: ['mocha'], |
|||
|
|||
|
|||
/** |
|||
* Run with chrome to enable debugging |
|||
* |
|||
* available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
|
|||
*/ |
|||
browsers: ['Chrome'] |
|||
}; |
|||
|
|||
config.set(_config); |
|||
}; |
|||
@ -0,0 +1,77 @@ |
|||
var webpackConfig = require('./webpack.coverage'); |
|||
|
|||
module.exports = function (config) { |
|||
var _config = { |
|||
/** |
|||
* Base path that will be used to resolve all patterns (e.g. files, exclude) |
|||
*/ |
|||
basePath: '', |
|||
|
|||
frameworks: ['jasmine'], |
|||
|
|||
/** |
|||
* Load additional test shim to setup angular2 for testing |
|||
*/ |
|||
files: [ |
|||
{ pattern: './app-config/karma-test-shim.js', watched: false } |
|||
], |
|||
|
|||
preprocessors: { |
|||
'./config/karma-test-shim.js': ['webpack', 'sourcemap'], |
|||
}, |
|||
|
|||
/** |
|||
* Load the files with webpack and use test configuration for it. |
|||
*/ |
|||
webpack: webpackConfig, |
|||
|
|||
webpackMiddleware: { |
|||
stats: 'errors-only' |
|||
}, |
|||
|
|||
webpackServer: { |
|||
noInfo: true |
|||
}, |
|||
|
|||
/* |
|||
* Use a mocha style console reporter, html reporter and the code coverage reporter |
|||
*/ |
|||
reporters: ['mocha', 'html', 'coverage'], |
|||
|
|||
// HtmlReporter configuration
|
|||
htmlReporter: { |
|||
useCompactStyle: true, |
|||
/** |
|||
* Use the same folder like the html report for coverage reports |
|||
*/ |
|||
outputFile: '_test-output/tests.html', |
|||
|
|||
/** |
|||
* Group the output by test suite (describe), equivalent to mocha reporter |
|||
*/ |
|||
groupSuites: true |
|||
}, |
|||
|
|||
coverageReporter: { |
|||
type: 'html', |
|||
/** |
|||
* Use the same folder like the html report for coverage reports |
|||
*/ |
|||
dir: '_test-output/coverage' |
|||
}, |
|||
|
|||
/** |
|||
* Disable continuous Integration mode, run only one time |
|||
*/ |
|||
singleRun: true, |
|||
|
|||
/** |
|||
* Run with chrome because phantom js does not provide all types, e.g. DragEvent |
|||
* |
|||
* available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
|
|||
*/ |
|||
browsers: ['PhantomJS'] |
|||
}; |
|||
|
|||
config.set(_config); |
|||
}; |
|||
@ -0,0 +1,117 @@ |
|||
// ReSharper disable InconsistentNaming
|
|||
// ReSharper disable PossiblyUnassignedProperty
|
|||
|
|||
var webpack = require('webpack'), |
|||
path = require('path'), |
|||
HtmlWebpackPlugin = require('html-webpack-plugin'), |
|||
ExtractTextPlugin = require('extract-text-webpack-plugin'), |
|||
helpers = require('./helpers'); |
|||
|
|||
module.exports = { |
|||
/** |
|||
* The entry point for the bundle |
|||
* Our Angular.js app |
|||
* |
|||
* See: http://webpack.github.io/docs/configuration.html#entry
|
|||
*/ |
|||
entry: { |
|||
'polyfills': './app/polyfills.ts', |
|||
'vendor': './app/vendor.ts', |
|||
'app': './app/main.ts' |
|||
}, |
|||
|
|||
/** |
|||
* Options affecting the resolving of modules. |
|||
* |
|||
* See: http://webpack.github.io/docs/configuration.html#resolve
|
|||
*/ |
|||
resolve: { |
|||
/** |
|||
* An array of extensions that should be used to resolve modules. |
|||
* |
|||
* See: http://webpack.github.io/docs/configuration.html#resolve-extensions
|
|||
*/ |
|||
extensions: ['', '.js', '.ts', '.css', '.scss'], |
|||
root: [ |
|||
helpers.root('app'), |
|||
helpers.root('app-libs') |
|||
] |
|||
}, |
|||
|
|||
/* |
|||
* Options affecting the normal modules. |
|||
* |
|||
* See: http://webpack.github.io/docs/configuration.html#module
|
|||
*/ |
|||
module: { |
|||
preLoaders: [{ |
|||
test: /\.ts/, |
|||
loader: helpers.root('app-config', 'auto-loader') + '?[file].html=template&[file].scss=styles', |
|||
}], |
|||
|
|||
/** |
|||
* An array of automatically applied loaders. |
|||
* |
|||
* IMPORTANT: The loaders here are resolved relative to the resource which they are applied to. |
|||
* This means they are not resolved relative to the configuration file. |
|||
* |
|||
* See: http://webpack.github.io/docs/configuration.html#module-loaders
|
|||
*/ |
|||
loaders: [ |
|||
{ |
|||
test: /\.ts$/, |
|||
loader: 'awesome-typescript-loader' |
|||
}, { |
|||
test: /\.html$/, |
|||
loader: 'html' |
|||
}, { |
|||
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)(\?.*$|$)/, |
|||
loader: 'file?name=assets/[name].[hash].[ext]' |
|||
}, { |
|||
test: /\.css$/, |
|||
loader: ExtractTextPlugin.extract('style', 'css?sourceMap') |
|||
}, { |
|||
test: /\.scss$/, |
|||
exclude: helpers.root('app', 'theme'), |
|||
loaders: ['raw', 'sass'] |
|||
} |
|||
] |
|||
}, |
|||
|
|||
plugins: [ |
|||
/** |
|||
* Plugin: CommonsChunkPlugin |
|||
* Description: Shares common code between the pages. |
|||
* It identifies common modules and put them into a commons chunk. |
|||
* |
|||
* See: https://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin
|
|||
*/ |
|||
new webpack.optimize.CommonsChunkPlugin({ |
|||
name: ['app', 'vendor', 'polyfills'] |
|||
}), |
|||
|
|||
/** |
|||
* Plugin: HtmlWebpackPlugin |
|||
* Description: Simplifies creation of HTML files to serve your webpack bundles. |
|||
* This is especially useful for webpack bundles that include a hash in the filename |
|||
* which changes every compilation. |
|||
* |
|||
* See: https://github.com/ampedandwired/html-webpack-plugin
|
|||
*/ |
|||
new HtmlWebpackPlugin({ |
|||
template: 'wwwroot/index.html' |
|||
}), |
|||
|
|||
new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /en/), |
|||
|
|||
/** |
|||
* Shim additional libraries |
|||
* |
|||
* See: https://webpack.github.io/docs/shimming-modules.html
|
|||
*/ |
|||
new webpack.ProvidePlugin({ |
|||
// Mouse trap handles shortcut management
|
|||
'Mousetrap': 'mousetrap/mousetrap' |
|||
}) |
|||
] |
|||
}; |
|||
@ -0,0 +1,23 @@ |
|||
|
|||
var webpackMerge = require('webpack-merge'), |
|||
path = require('path'), |
|||
helpers = require('./helpers'), |
|||
testConfig = require('./webpack.test.js'); |
|||
|
|||
module.exports = webpackMerge(testConfig, { |
|||
module: { |
|||
postLoaders: [ |
|||
{ |
|||
test: /\.(js|ts)$/, |
|||
include: helpers.root('app'), |
|||
exclude: [/\.(e2e|spec)\.ts$/], |
|||
loader: 'istanbul-instrumenter-loader' |
|||
}, { |
|||
test: /\.(js|ts)$/, |
|||
include: helpers.root('app'), |
|||
exclude: [/\.(e2e|spec)\.ts$/], |
|||
loader: helpers.root('app-config', 'fix-coverage-loader') |
|||
} |
|||
] |
|||
} |
|||
}); |
|||
@ -0,0 +1,67 @@ |
|||
// ReSharper disable InconsistentNaming
|
|||
// ReSharper disable PossiblyUnassignedProperty
|
|||
|
|||
var webpackMerge = require('webpack-merge'), |
|||
ExtractTextPlugin = require('extract-text-webpack-plugin'), |
|||
commonConfig = require('./webpack.common.js'), |
|||
helpers = require('./helpers'); |
|||
|
|||
module.exports = webpackMerge(commonConfig, { |
|||
/** |
|||
* Developer tool to enhance debugging |
|||
* |
|||
* See: http://webpack.github.io/docs/configuration.html#devtool
|
|||
* See: https://github.com/webpack/docs/wiki/build-performance#sourcemaps
|
|||
*/ |
|||
devtool: 'cheap-module-eval-source-map', |
|||
|
|||
output: { |
|||
filename: '[name].js', |
|||
// Set the public path, because we are running the website from another port (5000)
|
|||
publicPath: 'http://localhost:3000/' |
|||
}, |
|||
|
|||
/* |
|||
* Options affecting the normal modules. |
|||
* |
|||
* See: http://webpack.github.io/docs/configuration.html#module
|
|||
*/ |
|||
module: { |
|||
/** |
|||
* An array of automatically applied loaders. |
|||
* |
|||
* IMPORTANT: The loaders here are resolved relative to the resource which they are applied to. |
|||
* This means they are not resolved relative to the configuration file. |
|||
* |
|||
* See: http://webpack.github.io/docs/configuration.html#module-loaders
|
|||
*/ |
|||
loaders: [ |
|||
{ |
|||
test: /\.scss$/, |
|||
include: helpers.root('app', 'theme'), |
|||
loaders: ['style', 'css', 'sass?sourceMap'] |
|||
} |
|||
] |
|||
}, |
|||
|
|||
plugins: [ |
|||
new ExtractTextPlugin('[name].css') |
|||
], |
|||
|
|||
tslint: { |
|||
/** |
|||
* Run tslint in production build, but do not fail if there is a warning. |
|||
* |
|||
* See: https://github.com/wbuchwalter/tslint-loader
|
|||
*/ |
|||
failOnHint: false, |
|||
/** |
|||
* Share the configuration file with the IDE |
|||
*/ |
|||
configuration: require('./../tslint.json') |
|||
}, |
|||
|
|||
devServer: { |
|||
historyApiFallback: true, stats: 'minimal' |
|||
} |
|||
}); |
|||
@ -0,0 +1,106 @@ |
|||
var webpack = require('webpack'), |
|||
webpackMerge = require('webpack-merge'), |
|||
ExtractTextPlugin = require('extract-text-webpack-plugin'), |
|||
commonConfig = require('./webpack.common.js'), |
|||
helpers = require('./helpers'); |
|||
|
|||
const ENV = process.env.NODE_ENV = process.env.ENV = 'production'; |
|||
|
|||
module.exports = webpackMerge(commonConfig, { |
|||
devtool: 'source-map', |
|||
|
|||
output: { |
|||
/** |
|||
* The output directory as absolute path (required). |
|||
* |
|||
* See: http://webpack.github.io/docs/configuration.html#output-path
|
|||
*/ |
|||
path: helpers.root('wwwroot/build/'), |
|||
|
|||
publicPath: '/build/', |
|||
|
|||
/** |
|||
* Specifies the name of each output file on disk. |
|||
* IMPORTANT: You must not specify an absolute path here! |
|||
* |
|||
* See: http://webpack.github.io/docs/configuration.html#output-filename
|
|||
*/ |
|||
filename: '[name].[hash].js', |
|||
|
|||
/** |
|||
* The filename of non-entry chunks as relative path |
|||
* inside the output.path directory. |
|||
* |
|||
* See: http://webpack.github.io/docs/configuration.html#output-chunkfilename
|
|||
*/ |
|||
chunkFilename: '[id].[hash].chunk.js' |
|||
}, |
|||
|
|||
/* |
|||
* Options affecting the normal modules. |
|||
* |
|||
* See: http://webpack.github.io/docs/configuration.html#module
|
|||
*/ |
|||
module: { |
|||
preLoaders: [{ |
|||
test: /\.ts$/, |
|||
loader: "tslint" |
|||
}], |
|||
|
|||
/** |
|||
* An array of automatically applied loaders. |
|||
* |
|||
* IMPORTANT: The loaders here are resolved relative to the resource which they are applied to. |
|||
* This means they are not resolved relative to the configuration file. |
|||
* |
|||
* See: http://webpack.github.io/docs/configuration.html#module-loaders
|
|||
*/ |
|||
loaders: [ |
|||
{ |
|||
test: /\.scss$/, |
|||
include: helpers.root('app', 'theme'), |
|||
loader: ExtractTextPlugin.extract('style', 'css!sass?sourceMap') |
|||
} |
|||
] |
|||
}, |
|||
|
|||
tslint: { |
|||
/** |
|||
* Run tslint in production build and fail if there is one warning. |
|||
* |
|||
* See: https://github.com/wbuchwalter/tslint-loader
|
|||
*/ |
|||
failOnHint: true, |
|||
/** |
|||
* Share the configuration file with the IDE |
|||
*/ |
|||
configuration: require('./../tslint.json') |
|||
}, |
|||
|
|||
/** |
|||
* Html loader advanced options |
|||
* |
|||
* See: https://github.com/webpack/html-loader#advanced-options
|
|||
*/ |
|||
htmlLoader: { |
|||
minimize: false |
|||
}, |
|||
|
|||
plugins: [ |
|||
new webpack.NoErrorsPlugin(), |
|||
new webpack.optimize.DedupePlugin(), |
|||
new webpack.optimize.UglifyJsPlugin({ mangle: { screw_ie8: true, keep_fnames: true } }), |
|||
new webpack.DefinePlugin({ 'process.env': { 'ENV': JSON.stringify(ENV) } }), |
|||
new ExtractTextPlugin('[name].[hash].css'), |
|||
|
|||
function () { |
|||
this.plugin("done", function (stats) { |
|||
if (stats.compilation.errors && stats.compilation.errors.length && process.argv.indexOf('--watch') == -1) { |
|||
console.log(stats.compilation.errors); |
|||
|
|||
throw new Error('webpack build failed.'); |
|||
} |
|||
}); |
|||
} |
|||
] |
|||
}); |
|||
@ -0,0 +1,77 @@ |
|||
var webpack = require('webpack'), |
|||
helpers = require('./helpers'); |
|||
|
|||
module.exports = { |
|||
/** |
|||
* Source map for Karma from the help of karma-sourcemap-loader & karma-webpack |
|||
* |
|||
* Do not change, leave as is or it wont work. |
|||
* See: https://github.com/webpack/karma-webpack#source-maps
|
|||
*/ |
|||
devtool: 'inline-source-map', |
|||
|
|||
resolve: { |
|||
/** |
|||
* An array of extensions that should be used to resolve modules. |
|||
* |
|||
* See: http://webpack.github.io/docs/configuration.html#resolve-extensions
|
|||
*/ |
|||
extensions: ['', '.ts', '.js'], |
|||
root: [ |
|||
helpers.root('app'), |
|||
helpers.root('app-libs') |
|||
] |
|||
}, |
|||
|
|||
/* |
|||
* Options affecting the normal modules. |
|||
* |
|||
* See: http://webpack.github.io/docs/configuration.html#module
|
|||
*/ |
|||
module: { |
|||
preLoaders: [{ |
|||
test: /\.ts/, |
|||
loader: helpers.root('app-config', 'auto-loader') + '?[file].html=template&[file].scss=styles', |
|||
}], |
|||
|
|||
/** |
|||
* An array of automatically applied loaders. |
|||
* |
|||
* IMPORTANT: The loaders here are resolved relative to the resource which they are applied to. |
|||
* This means they are not resolved relative to the configuration file. |
|||
* |
|||
* See: http://webpack.github.io/docs/configuration.html#module-loaders
|
|||
*/ |
|||
loaders: [ |
|||
{ |
|||
test: /\.ts$/, |
|||
loader: 'awesome-typescript-loader' |
|||
}, { |
|||
test: /\.html$/, |
|||
loader: 'html' |
|||
}, { |
|||
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)(\?.*$|$)/, |
|||
loader: 'null' |
|||
}, { |
|||
test: /\.css$/, |
|||
loader: 'null' |
|||
}, { |
|||
test: /\.scss$/, |
|||
exclude: helpers.root('app', 'theme'), |
|||
loaders: ['raw', 'sass'] |
|||
} |
|||
] |
|||
}, |
|||
|
|||
plugins: [ |
|||
/** |
|||
* Shim additional libraries |
|||
* |
|||
* See: https://webpack.github.io/docs/shimming-modules.html
|
|||
*/ |
|||
new webpack.ProvidePlugin({ |
|||
// Mouse trap handles shortcut management
|
|||
'Mousetrap': 'mousetrap/mousetrap' |
|||
}) |
|||
] |
|||
} |
|||
@ -0,0 +1,2 @@ |
|||
declare var styles: string[]; |
|||
declare var template: string; |
|||
@ -0,0 +1,3 @@ |
|||
<main> |
|||
<h1>Hello from Angular 2 App with Webpack!</h1> |
|||
</main> |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"app.component.js","sourceRoot":"","sources":["app.component.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,IAAY,GAAG,WAAM,eAAe,CAAC,CAAA;AAOrC;IAAA;IAA4B,CAAC;IAL7B;QAAC,GAAG,CAAC,SAAS,CAAC;YACX,QAAQ,EAAE,QAAQ;YAClB,UAAA,QAAQ;YACR,QAAA,MAAM;SACT,CAAC;;oBAAA;IAC0B,mBAAC;AAAD,CAAC,AAA7B,IAA6B;AAAhB,oBAAY,eAAI,CAAA"} |
|||
@ -0,0 +1,8 @@ |
|||
main { |
|||
padding: 1em; |
|||
font-family: Arial, Helvetica, sans-serif; |
|||
font-size: 1.1rem; |
|||
text-align: center; |
|||
margin-top: 50px; |
|||
display: block; |
|||
} |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"app.component.spec.js","sourceRoot":"","sources":["app.component.spec.ts"],"names":[],"mappings":";AAAA,wBAAwB,uBAAuB,CAAC,CAAA;AAEhD,8BAA6B,iBAAiB,CAAC,CAAA;AAE/C,QAAQ,CAAC,KAAK,EAAE;IACZ,UAAU,CAAC;QACP,iBAAO,CAAC,sBAAsB,CAAC,EAAE,YAAY,EAAE,CAAC,4BAAY,CAAC,EAAE,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,aAAa,EAAE;QACd,IAAM,OAAO,GAAG,iBAAO,CAAC,eAAe,CAAC,4BAAY,CAAC,CAAC;QAEtD,MAAM,CAAC,OAAO,CAAC,iBAAiB,YAAY,4BAAY,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,4BAA4B,CAAC,CAAC;IACvG,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} |
|||
@ -0,0 +1,15 @@ |
|||
import { TestBed } from '@angular/core/testing'; |
|||
|
|||
import { AppComponent } from './app.component'; |
|||
|
|||
describe('App', () => { |
|||
beforeEach(() => { |
|||
TestBed.configureTestingModule({ declarations: [AppComponent] }); |
|||
}); |
|||
|
|||
it('should work', () => { |
|||
const fixture = TestBed.createComponent(AppComponent); |
|||
|
|||
expect(fixture.componentInstance instanceof AppComponent).toBe(true, 'should create AppComponent'); |
|||
}); |
|||
}); |
|||
@ -0,0 +1,8 @@ |
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
@Ng2.Component({ |
|||
selector: 'my-app', |
|||
template, |
|||
styles |
|||
}) |
|||
export class AppComponent { } |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"app.module.js","sourceRoot":"","sources":["app.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,IAAY,GAAG,WAAM,eAAe,CAAC,CAAA;AAErC,iCAA8B,2BAA2B,CAAC,CAAA;AAE1D,8BAA6B,iBAAiB,CAAC,CAAA;AAW/C;IAAA;IAAyB,CAAC;IAT1B;QAAC,GAAG,CAAC,QAAQ,CAAC;YACV,OAAO,EAAE;gBACL,gCAAa;aAChB;YACD,YAAY,EAAE;gBACV,4BAAY;aACf;YACD,SAAS,EAAE,CAAC,4BAAY,CAAC;SAC5B,CAAC;;iBAAA;IACuB,gBAAC;AAAD,CAAC,AAA1B,IAA0B;AAAb,iBAAS,YAAI,CAAA"} |
|||
@ -0,0 +1,16 @@ |
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
import { BrowserModule } from '@angular/platform-browser'; |
|||
|
|||
import { AppComponent } from './app.component'; |
|||
|
|||
@Ng2.NgModule({ |
|||
imports: [ |
|||
BrowserModule |
|||
], |
|||
declarations: [ |
|||
AppComponent |
|||
], |
|||
bootstrap: [AppComponent] |
|||
}) |
|||
export class AppModule { } |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"action.js","sourceRoot":"","sources":["action.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,IAAM,UAAU,GAAG,cAAQ,CAAC,CAAC;AAE7B;IACI,MAAM,CAAC,UAAU,MAAW,EAAE,GAAW;QACrC,IAAI,UAAe,CAAC;QACpB,IAAI,QAAa,CAAC;QAClB,IAAI,aAAkB,CAAC;QACvB,IAAI,YAAiB,CAAC;QAEtB;YACI,IAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;YAE7B,EAAE,CAAC,CAAC,KAAK,IAAI,UAAU,IAAI,UAAU,CAAC,SAAS,IAAI,OAAO,UAAU,CAAC,SAAS,KAAK,UAAU,CAAC,CAAC,CAAC;gBAC5F,YAAY,GAAG,UAAU,CAAC,SAAS,CAAC,UAAC,CAAM,IAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAE/E,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACrC,CAAC;QACL,CAAC;QAAA,CAAC;QAEF;YACI,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;gBACf,YAAY,CAAC,WAAW,EAAE,CAAC;gBAE3B,aAAa,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;YAC9D,CAAC;QACL,CAAC;QAAA,CAAC;QAEF,EAAE,CAAC,CAAC,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACrB,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE;gBAC/B,GAAG,EAAE;oBACD,MAAM,CAAC,UAAU,CAAC;gBACtB,CAAC;gBACD,GAAG,EAAE,UAAU,CAAC;oBACZ,QAAQ,GAAG,IAAI,CAAC;oBAEhB,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC;wBAC7B,QAAQ,CAAC,gBAAgB,GAAG,EAAE,CAAC;wBAE/B,IAAI,SAAO,GAAG,QAAQ,CAAC,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,UAAU,CAAC;wBAEtF,QAAQ,CAAC,WAAW,GAAG;4BACnB,GAAG,CAAC,CAAU,UAAa,EAAb,+BAAa,EAAb,2BAAa,EAAb,IAAa,CAAC;gCAAvB,IAAI,CAAC,sBAAA;gCACN,CAAC,CAAC,WAAW,EAAE,CAAC;6BACnB;4BAED,QAAQ,CAAC,gBAAgB,GAAG,IAAI,CAAC;4BAEjC,SAAO,EAAE,CAAC;wBACd,CAAC,CAAC;oBACN,CAAC;oBAED,aAAa,GAAG,QAAQ,CAAC,gBAAgB,CAAC;oBAE1C,UAAU,GAAG,CAAC,CAAC;oBAEf,WAAW,EAAE,CAAC;oBACd,SAAS,EAAE,CAAC;gBAChB,CAAC;aACJ,CAAC,CAAC;QACP,CAAC;IACL,CAAC,CAAC;AACN,CAAC;AA3De,cAAM,SA2DrB,CAAA"} |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"action.spec.js","sourceRoot":"","sources":["action.spec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;;;;;;;;;;AAEH,qBAAwB,MAAM,CAAC,CAAA;AAE/B,iBAAuB,OAAO,CAAC,CAAA;AAE/B;IACI,sBAAoB,QAAc,EAAE,GAAG;QAA3B,wBAAsB,GAAtB,gBAAsB;QAAd,aAAQ,GAAR,QAAQ,CAAM;QAE3B,oBAAe,GAAG,KAAK,CAAC;QAGxB,WAAM,GAAG,IAAI,cAAO,EAAU,CAAC,GAAG,CAAC,UAAA,CAAC,IAAM,MAAM,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAG7E,WAAM,GAAG,IAAI,cAAO,EAAU,CAAC,GAAG,CAAC,UAAA,CAAC,IAAM,MAAM,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IARzC,CAAC;IAUrC,2BAAI,GAAX;QACI,IAAI,CAAC,MAAM,GAAG,IAAI,cAAO,EAAU,CAAC,GAAG,CAAC,UAAA,CAAC,IAAM,MAAM,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACtF,CAAC;IAEM,kCAAW,GAAlB;QACI,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;IAChC,CAAC;IAZD;QAAC,SAAM,EAAE;;gDAAA;IAGT;QAAC,SAAM,EAAE;;gDAAA;IAUb,mBAAC;AAAD,CAAC,AAlBD,IAkBC;AAED,QAAQ,CAAC,QAAQ,EAAE;IACf,EAAE,CAAC,+EAA+E,EAAE;QAChF,IAAI,aAAa,GAAG,CAAC,CAAC;QAEtB,IAAM,KAAK,GAAG;YACV,IAAI,EAAE,UAAC,CAAM;gBACT,aAAa,EAAE,CAAC;gBAEhB,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACvC,CAAC;SACJ,CAAC;QAEF,IAAM,IAAI,GAAG,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC;QAErC,IAAI,CAAC,IAAI,EAAE,CAAC;QAEN,IAAI,CAAC,MAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1B,IAAI,CAAC,MAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAEhC,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAE9B,IAAI,CAAC,WAAW,EAAE,CAAC;QAEb,IAAI,CAAC,MAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1B,IAAI,CAAC,MAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAEhC,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,UAAU,EAAE,CAAC;IAC9C,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} |
|||
@ -0,0 +1,61 @@ |
|||
/* |
|||
* Athene Requirements Center |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import { Subject } from 'rxjs'; |
|||
|
|||
import { Action } from './../'; |
|||
|
|||
class MockupObject { |
|||
constructor(private readonly store: any) { } |
|||
|
|||
public isDestroyCalled = false; |
|||
|
|||
@Action() |
|||
public event1 = new Subject<string>().map(x => { return { type: 'MOCK_ACTION' }; }); |
|||
|
|||
@Action() |
|||
public event2 = new Subject<string>().map(x => { return { type: 'MOCK_ACTION' }; }); |
|||
|
|||
public init() { |
|||
this.event2 = new Subject<string>().map(x => { return { type: 'MOCK_ACTION' }; }); |
|||
} |
|||
|
|||
public ngOnDestroy() { |
|||
this.isDestroyCalled = true; |
|||
} |
|||
} |
|||
|
|||
describe('Action', () => { |
|||
it('should test complete flow to subscribe and unsubscribe and to trigger actions', () => { |
|||
let dispatchCount = 0; |
|||
|
|||
const state = { |
|||
next: (e: any) => { |
|||
dispatchCount++; |
|||
|
|||
expect(e.type).toBe('MOCK_ACTION'); |
|||
} |
|||
}; |
|||
|
|||
const mock = new MockupObject(state); |
|||
|
|||
mock.init(); |
|||
|
|||
(<any>mock.event1).next('TEST'); |
|||
(<any>mock.event2).next('TEST'); |
|||
|
|||
expect(dispatchCount).toBe(2); |
|||
|
|||
mock.ngOnDestroy(); |
|||
|
|||
(<any>mock.event1).next('TEST'); |
|||
(<any>mock.event2).next('TEST'); |
|||
|
|||
expect(dispatchCount).toBe(2); |
|||
expect(mock.isDestroyCalled).toBeTruthy(); |
|||
}); |
|||
}); |
|||
@ -0,0 +1,69 @@ |
|||
/* |
|||
* Athene Requirements Center |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
const EMPTY_FUNC = () => { }; |
|||
|
|||
export function Action() { |
|||
return function (target: any, key: string) { |
|||
let observable: any; |
|||
let instance: any; |
|||
let subscriptions: any; |
|||
let subscription: any; |
|||
|
|||
function subscribe() { |
|||
const store = instance.store; |
|||
|
|||
if (store && observable && observable.subscribe && typeof observable.subscribe === 'function') { |
|||
subscription = observable.subscribe((a: any) => { if (a) { store.next(a); } }); |
|||
|
|||
subscriptions.push(subscription); |
|||
} |
|||
}; |
|||
|
|||
function unsubscribe() { |
|||
if (subscription) { |
|||
subscription.unsubscribe(); |
|||
|
|||
subscriptions.splice(subscriptions.indexOf(subscribe), 1); |
|||
} |
|||
}; |
|||
|
|||
if (delete target[key]) { |
|||
Object.defineProperty(target, key, { |
|||
get: function () { |
|||
return observable; |
|||
}, |
|||
set: function (v) { |
|||
instance = this; |
|||
|
|||
if (!instance.___subscriptions) { |
|||
instance.___subscriptions = []; |
|||
|
|||
let destroy = instance.ngOnDestroy ? instance.ngOnDestroy.bind(instance) : EMPTY_FUNC; |
|||
|
|||
instance.ngOnDestroy = () => { |
|||
for (let s of subscriptions) { |
|||
s.unsubscribe(); |
|||
} |
|||
|
|||
instance.___subscriptions = null; |
|||
|
|||
destroy(); |
|||
}; |
|||
} |
|||
|
|||
subscriptions = instance.___subscriptions; |
|||
|
|||
observable = v; |
|||
|
|||
unsubscribe(); |
|||
subscribe(); |
|||
} |
|||
}); |
|||
} |
|||
}; |
|||
} |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"cloak.directive.js","sourceRoot":"","sources":["cloak.directive.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;;;;;;;;;;AAEH,IAAY,GAAG,WAAM,eAAe,CAAC,CAAA;AAKrC;IACI,wBAAoB,QAAgB,EAAE,GAAG,EAAC,UAAU;QAAxC,wBAAwB,GAAxB,kBAAwB;QAAhB,aAAQ,GAAR,QAAQ,CAAQ;IAAoB,CAAC;IAElD,iCAAQ,GAAf;QACI,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC5D,CAAC;IARL;QAAC,GAAG,CAAC,SAAS,CAAC;YACX,QAAQ,EAAE,WAAW;SACxB,CAAC;;sBAAA;IAOF,qBAAC;AAAD,CAAC,AAND,IAMC;AANY,sBAAc,iBAM1B,CAAA"} |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"cloak.directive.spec.js","sourceRoot":"","sources":["cloak.directive.spec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,gCAA+B,mBAAmB,CAAC,CAAA;AAEnD,QAAQ,CAAC,gBAAgB,EAAE;IACvB,EAAE,CAAC,8CAA8C,EAAE;QAC/C,IAAI,MAAM,GAAG,KAAK,CAAC;QAEnB,IAAM,OAAO,GAAG;YACZ,aAAa,EAAE;gBACX,SAAS,EAAE;oBACP,MAAM,EAAE;wBACJ,MAAM,GAAG,IAAI,CAAC;oBAClB,CAAC;iBACJ;aACJ;SACJ,CAAC;QAED,IAAI,gCAAc,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC;QAExC,MAAM,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,CAAC;IAChC,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} |
|||
@ -0,0 +1,28 @@ |
|||
/* |
|||
* Athene Requirements Center |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import { CloakDirective } from './cloak.directive'; |
|||
|
|||
describe('CloakDirective', () => { |
|||
it('should remove class from element on ngOnInit', () => { |
|||
let called = false; |
|||
|
|||
const element = { |
|||
nativeElement: { |
|||
classList: { |
|||
remove: () => { |
|||
called = true; |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
|
|||
new CloakDirective(element).ngOnInit(); |
|||
|
|||
expect(called).toBeTruthy(); |
|||
}); |
|||
}); |
|||
@ -0,0 +1,19 @@ |
|||
/* |
|||
* Athene Requirements Center |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
@Ng2.Directive({ |
|||
selector: '.gp-cloak' |
|||
}) |
|||
export class CloakDirective implements Ng2.OnInit { |
|||
constructor(private readonly element: Ng2.ElementRef) { } |
|||
|
|||
public ngOnInit() { |
|||
this.element.nativeElement.classList.remove('gp-cloak'); |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
<div class="btn-group" [class.open]="isOpen"> |
|||
<button type="button" class="btn btn-secondary btn-sm" (click)="toggleOpen()" [style.background]="selectedColor.toString()"></button> |
|||
|
|||
<div class="dropdown-menu dropdown-menu-right"> |
|||
<div class="color-palette"> |
|||
<span *ngFor="let color of palette.colors" class="color-palette-box" (click)="selectColor(color)" [class.selected]="selectedColor && color.eq(selectedColor)"> |
|||
<span class="color-palette-color" [style.background]="color.toString()"></span> |
|||
</span> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"color-picker.component.js","sourceRoot":"","sources":["color-picker.component.ts"],"names":[],"mappings":"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"} |
|||
@ -0,0 +1,56 @@ |
|||
@import '../../theme/_mixins.scss'; |
|||
|
|||
$color-size: 24px; |
|||
$button-size: 1.81rem; |
|||
|
|||
.color-palette { |
|||
& { |
|||
@include clearfix(); |
|||
width: 8 * ($color-size + 6); |
|||
padding: 6px; |
|||
} |
|||
|
|||
&-box { |
|||
margin: 2px; |
|||
border: 2px solid transparent; |
|||
width: $color-size; |
|||
height: $color-size; |
|||
float: left; |
|||
} |
|||
|
|||
&-box:hover { |
|||
border-color: #1460A8; |
|||
} |
|||
|
|||
&-box.selected { |
|||
border-color: #1875CC; |
|||
} |
|||
|
|||
&-box.selected:hover { |
|||
border-color: #1875CC; |
|||
} |
|||
|
|||
&-box.disabled { |
|||
border-color: transparent; |
|||
} |
|||
|
|||
&-color { |
|||
border: 1px solid white; |
|||
width: $color-size - 4; |
|||
height: $color-size - 4; |
|||
display: block; |
|||
} |
|||
} |
|||
|
|||
.dropdown-menu { |
|||
background: #eee; |
|||
} |
|||
|
|||
.btn-group > .btn:first-child { |
|||
@include border-radius(0.25em); |
|||
} |
|||
|
|||
.btn { |
|||
width: $button-size; |
|||
height: $button-size; |
|||
} |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"color-picker.component.spec.js","sourceRoot":"","sources":["color-picker.component.spec.ts"],"names":[],"mappings":"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"} |
|||
@ -0,0 +1,124 @@ |
|||
/* |
|||
* Athene Requirements Center |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import { Color } from './../'; |
|||
|
|||
import { ColorPickerComponent } from './color-picker.component'; |
|||
|
|||
describe('ColorPickerComponent', () => { |
|||
it('should instantiate', () => { |
|||
const colorPicker = new ColorPickerComponent({ nativeElement: {} }); |
|||
|
|||
expect(colorPicker).toBeDefined(); |
|||
}); |
|||
|
|||
it('should close color picker when clicking outside of the modal', () => { |
|||
const element = { |
|||
nativeElement: { |
|||
contains: () => { |
|||
return false; |
|||
} |
|||
} |
|||
}; |
|||
|
|||
const colorPicker = new ColorPickerComponent(element); |
|||
colorPicker.open(); |
|||
colorPicker.onClick({}); |
|||
|
|||
expect(colorPicker.isOpen).toBeFalsy(); |
|||
}); |
|||
|
|||
it('should not close color picker when clicking inside the modal', () => { |
|||
const element = { |
|||
nativeElement: { |
|||
contains: () => { |
|||
return true; |
|||
} |
|||
} |
|||
}; |
|||
|
|||
const colorPicker = new ColorPickerComponent(element); |
|||
colorPicker.open(); |
|||
colorPicker.onClick({}); |
|||
|
|||
expect(colorPicker.isOpen).toBeTruthy(); |
|||
}); |
|||
|
|||
it('should close modal and emit event when setting color', () => { |
|||
const colorPicker = new ColorPickerComponent({ nativeElement: {} }); |
|||
const selectedColor = Color.RED; |
|||
|
|||
let lastColor: Color | null = null; |
|||
|
|||
colorPicker.colorChange.subscribe((c: Color) => { |
|||
lastColor = c; |
|||
}); |
|||
|
|||
colorPicker.open(); |
|||
colorPicker.selectColor(selectedColor); |
|||
|
|||
expect(lastColor).toBe(selectedColor); |
|||
expect(colorPicker.isOpen).toBeFalsy(); |
|||
}); |
|||
|
|||
it('should not emit event when selecting same color', () => { |
|||
const colorPicker = new ColorPickerComponent({ nativeElement: {} }); |
|||
const selectedColor = Color.RED; |
|||
|
|||
colorPicker.selectColor(selectedColor); |
|||
|
|||
let lastColor: Color | null = null; |
|||
|
|||
colorPicker.colorChange.subscribe((c: Color) => { |
|||
lastColor = c; |
|||
}); |
|||
|
|||
colorPicker.selectColor(selectedColor); |
|||
|
|||
expect(lastColor).toBeNull(); |
|||
}); |
|||
|
|||
it('should update selected color when component changes', () => { |
|||
const colorPicker = new ColorPickerComponent({ nativeElement: {} }); |
|||
const selectedColor = Color.RED; |
|||
|
|||
colorPicker.color = selectedColor; |
|||
|
|||
colorPicker.ngOnChanges({}); |
|||
|
|||
expect(colorPicker.selectedColor).toBe(selectedColor); |
|||
}); |
|||
|
|||
it('should update selected color with palette default if setting invalid color', () => { |
|||
const colorPicker = new ColorPickerComponent({ nativeElement: {} }); |
|||
|
|||
colorPicker.color = 'invalid'; |
|||
|
|||
colorPicker.ngOnChanges({}); |
|||
|
|||
expect(colorPicker.selectedColor).toBe(colorPicker.palette.defaultColor); |
|||
}); |
|||
|
|||
it('should update selected color with black if setting invalid color and palette is null', () => { |
|||
const colorPicker = new ColorPickerComponent({ nativeElement: {} }); |
|||
|
|||
colorPicker.palette = undefined!; |
|||
colorPicker.color = 'invalid'; |
|||
|
|||
colorPicker.ngOnChanges({}); |
|||
|
|||
expect(colorPicker.selectedColor).toBe(Color.BLACK); |
|||
}); |
|||
|
|||
it('should update isOpen prperty when toggleOpen is invoked', () => { |
|||
const colorPicker = new ColorPickerComponent({ nativeElement: {} }); |
|||
|
|||
colorPicker.toggleOpen(); |
|||
|
|||
expect(colorPicker.isOpen).toBeTruthy(); |
|||
}); |
|||
}); |
|||
@ -0,0 +1,96 @@ |
|||
/* |
|||
* Athene Requirements Center |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
import { Color } from './../utils/color'; |
|||
import { ColorPalette } from './../utils/color-palette'; |
|||
|
|||
@Ng2.Component({ |
|||
selector: 'gp-color-picker', |
|||
styles, |
|||
template |
|||
}) |
|||
export class ColorPickerComponent implements Ng2.OnChanges { |
|||
private selectedColorValue = new Color(0, 0, 0); |
|||
|
|||
@Ng2.Output() |
|||
public colorChange = new Ng2.EventEmitter(); |
|||
|
|||
@Ng2.Input() |
|||
public color: string | number | Color; |
|||
|
|||
@Ng2.Input() |
|||
public palette = ColorPalette.colors(); |
|||
|
|||
@Ng2.Input() |
|||
public isOpen = false; |
|||
|
|||
public get selectedColor(): Color { |
|||
return this.selectedColorValue; |
|||
} |
|||
|
|||
constructor(private readonly element: Ng2.ElementRef) { |
|||
this.updateColor(); |
|||
} |
|||
|
|||
@Ng2.HostListener('document:click', ['$event.target']) |
|||
public onClick(targetElement: any) { |
|||
const clickedInside = this.element.nativeElement.contains(targetElement); |
|||
|
|||
if (!clickedInside) { |
|||
this.close(); |
|||
} |
|||
} |
|||
|
|||
public ngOnChanges(changes: Ng2.SimpleChanges) { |
|||
this.updateColor(); |
|||
} |
|||
|
|||
public toggleOpen() { |
|||
this.isOpen = !this.isOpen; |
|||
} |
|||
|
|||
public close() { |
|||
this.isOpen = false; |
|||
} |
|||
|
|||
public open() { |
|||
this.isOpen = true; |
|||
} |
|||
|
|||
public selectColor(color: Color) { |
|||
this.updateParent(color); |
|||
this.updateColor(color); |
|||
this.close(); |
|||
} |
|||
|
|||
private updateParent(color: Color) { |
|||
if (this.selectedColorValue.ne(color)) { |
|||
this.colorChange.emit(color); |
|||
} |
|||
} |
|||
|
|||
private updateColor(color?: Color) { |
|||
let hasColor = false; |
|||
try { |
|||
this.selectedColorValue = Color.fromValue(color || this.color); |
|||
|
|||
hasColor = true; |
|||
} catch (e) { |
|||
hasColor = false; |
|||
} |
|||
|
|||
if (!hasColor || !this.selectedColorValue) { |
|||
if (this.palette) { |
|||
this.selectedColorValue = this.palette.defaultColor; |
|||
} else { |
|||
this.selectedColorValue = Color.BLACK; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"date-time.pipes.js","sourceRoot":"","sources":["date-time.pipes.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;;;;;;;;;;AAEH,IAAY,GAAG,WAAM,eAAe,CAAC,CAAA;AAQrC;IAAA;IAIA,CAAC;IAHU,iCAAS,GAAhB,UAAiB,KAAe,EAAE,IAAc;QAC5C,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC1C,CAAC;IANL;QAAC,GAAG,CAAC,IAAI,CAAC;YACN,IAAI,EAAE,WAAW;SACpB,CAAC;;qBAAA;IAKF,oBAAC;AAAD,CAAC,AAJD,IAIC;AAJY,qBAAa,gBAIzB,CAAA;AAKD;IAAA;IAIA,CAAC;IAHU,6BAAS,GAAhB,UAAiB,KAAe,EAAE,IAAc;QAC5C,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,CAAC;IANL;QAAC,GAAG,CAAC,IAAI,CAAC;YACN,IAAI,EAAE,OAAO;SAChB,CAAC;;iBAAA;IAKF,gBAAC;AAAD,CAAC,AAJD,IAIC;AAJY,iBAAS,YAIrB,CAAA;AAKD;IAAA;IAIA,CAAC;IAHU,iCAAS,GAAhB,UAAiB,KAAe,EAAE,IAAc;QAC5C,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IANL;QAAC,GAAG,CAAC,IAAI,CAAC;YACN,IAAI,EAAE,WAAW;SACpB,CAAC;;qBAAA;IAKF,oBAAC;AAAD,CAAC,AAJD,IAIC;AAJY,qBAAa,gBAIzB,CAAA;AAKD;IAAA;IAIA,CAAC;IAHU,2BAAS,GAAhB,UAAiB,KAAe,EAAE,IAAc;QAC5C,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IANL;QAAC,GAAG,CAAC,IAAI,CAAC;YACN,IAAI,EAAE,KAAK;SACd,CAAC;;eAAA;IAKF,cAAC;AAAD,CAAC,AAJD,IAIC;AAJY,eAAO,UAInB,CAAA;AAKD;IAAA;IAIA,CAAC;IAHU,iCAAS,GAAhB,UAAiB,KAAe,EAAE,IAAc;QAC5C,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC;IANL;QAAC,GAAG,CAAC,IAAI,CAAC;YACN,IAAI,EAAE,WAAW;SACpB,CAAC;;qBAAA;IAKF,oBAAC;AAAD,CAAC,AAJD,IAIC;AAJY,qBAAa,gBAIzB,CAAA;AAKD;IAAA;IAIA,CAAC;IAHU,gCAAS,GAAhB,UAAiB,KAAe,EAAE,IAAc;QAC5C,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC5B,CAAC;IANL;QAAC,GAAG,CAAC,IAAI,CAAC;YACN,IAAI,EAAE,UAAU;SACnB,CAAC;;oBAAA;IAKF,mBAAC;AAAD,CAAC,AAJD,IAIC;AAJY,oBAAY,eAIxB,CAAA"} |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"date-time.pipes.spec.js","sourceRoot":"","sources":["date-time.pipes.spec.ts"],"names":[],"mappings":"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"} |
|||
@ -0,0 +1,87 @@ |
|||
/* |
|||
* Athene Requirements Center |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import { DateTime, Duration } from './../'; |
|||
|
|||
import { |
|||
DayOfWeekPipe, |
|||
DayPipe, |
|||
DurationPipe, |
|||
MonthPipe, |
|||
ShortDatePipe, |
|||
ShortTimePipe, |
|||
} from './date-time.pipes'; |
|||
|
|||
const dateTime = DateTime.parse('2013-10-03T12:13:14.125', DateTime.iso8601()); |
|||
|
|||
describe('DurationPipe', () => { |
|||
it('should format to standard duration string', () => { |
|||
const duration = Duration.create(dateTime, dateTime.addMinutes(10).addDays(13)); |
|||
|
|||
const pipe = new DurationPipe(); |
|||
|
|||
const actual = pipe.transform(duration, []); |
|||
const expected = '312:10h'; |
|||
|
|||
expect(actual).toBe(expected); |
|||
}); |
|||
}); |
|||
|
|||
describe('DayPipe', () => { |
|||
it('should format to day numbers', () => { |
|||
const pipe = new DayPipe(); |
|||
|
|||
const actual = pipe.transform(dateTime, []); |
|||
const expected = '03'; |
|||
|
|||
expect(actual).toBe(expected); |
|||
}); |
|||
}); |
|||
|
|||
describe('MonthPipe', () => { |
|||
it('should format to long month name', () => { |
|||
const pipe = new MonthPipe(); |
|||
|
|||
const actual = pipe.transform(dateTime, []); |
|||
const expected = 'October'; |
|||
|
|||
expect(actual).toBe(expected); |
|||
}); |
|||
}); |
|||
|
|||
describe('DayOfWeekPipe', () => { |
|||
it('should format to short week of day string', () => { |
|||
const pipe = new DayOfWeekPipe(); |
|||
|
|||
const actual = pipe.transform(dateTime, []); |
|||
const expected = 'Th'; |
|||
|
|||
expect(actual).toBe(expected); |
|||
}); |
|||
}); |
|||
|
|||
describe('ShortDatePipe', () => { |
|||
it('should format to two digit day number and short month name', () => { |
|||
const pipe = new ShortDatePipe(); |
|||
|
|||
const actual = pipe.transform(dateTime, []); |
|||
const expected = '03.Oct'; |
|||
|
|||
expect(actual).toBe(expected); |
|||
}); |
|||
}); |
|||
|
|||
describe('ShortTimePipe', () => { |
|||
it('should format to short time string', () => { |
|||
const pipe = new ShortTimePipe(); |
|||
|
|||
const actual = pipe.transform(dateTime, []); |
|||
const expected = '12:13'; |
|||
|
|||
expect(actual).toBe(expected); |
|||
}); |
|||
}); |
|||
@ -0,0 +1,65 @@ |
|||
/* |
|||
* Athene Requirements Center |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
import { DateTime } from './../utils/date-time'; |
|||
import { Duration } from './../utils/duration'; |
|||
|
|||
@Ng2.Pipe({ |
|||
name: 'shortDate' |
|||
}) |
|||
export class ShortDatePipe { |
|||
public transform(value: DateTime, args: string[]): any { |
|||
return value.toStringFormat('DD.MMM'); |
|||
} |
|||
} |
|||
|
|||
@Ng2.Pipe({ |
|||
name: 'month' |
|||
}) |
|||
export class MonthPipe { |
|||
public transform(value: DateTime, args: string[]): any { |
|||
return value.toStringFormat('MMMM'); |
|||
} |
|||
} |
|||
|
|||
@Ng2.Pipe({ |
|||
name: 'dayOfWeek' |
|||
}) |
|||
export class DayOfWeekPipe { |
|||
public transform(value: DateTime, args: string[]): any { |
|||
return value.toStringFormat('dd'); |
|||
} |
|||
} |
|||
|
|||
@Ng2.Pipe({ |
|||
name: 'day' |
|||
}) |
|||
export class DayPipe { |
|||
public transform(value: DateTime, args: string[]): any { |
|||
return value.toStringFormat('DD'); |
|||
} |
|||
} |
|||
|
|||
@Ng2.Pipe({ |
|||
name: 'shortTime' |
|||
}) |
|||
export class ShortTimePipe { |
|||
public transform(value: DateTime, args: string[]): any { |
|||
return value.toStringFormat('HH:mm'); |
|||
} |
|||
} |
|||
|
|||
@Ng2.Pipe({ |
|||
name: 'duration' |
|||
}) |
|||
export class DurationPipe { |
|||
public transform(value: Duration, args: string[]): any { |
|||
return value.toString(); |
|||
} |
|||
} |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"drag-model.directive.js","sourceRoot":"","sources":["drag-model.directive.ts"],"names":[],"mappings":"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"} |
|||
@ -0,0 +1,117 @@ |
|||
/* |
|||
* Athene Requirements Center |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
import { DragService, Vec2 } from './../'; |
|||
|
|||
@Ng2.Directive({ |
|||
selector: '[gpDragModel]' |
|||
}) |
|||
export class DragModelDirective { |
|||
private startOffset: Vec2; |
|||
private startPosition: Vec2; |
|||
private mouseMoveSubscription: Function | null; |
|||
private mouseUpSubscription: Function | null; |
|||
private clonedElement: HTMLElement | null; |
|||
|
|||
@Ng2.Input('gpDragModel') |
|||
public model: any; |
|||
|
|||
constructor( |
|||
private readonly element: Ng2.ElementRef, |
|||
private readonly renderer: Ng2.Renderer, |
|||
private readonly dragService: DragService |
|||
) { |
|||
} |
|||
|
|||
@Ng2.HostListener('mousedown', ['$event']) |
|||
public onMouseDown(event: MouseEvent) { |
|||
this.startOffset = new Vec2(event.offsetX, event.offsetY); |
|||
this.startPosition = new Vec2(event.clientX, event.clientY); |
|||
|
|||
this.mouseMoveSubscription = |
|||
this.renderer.listenGlobal('window', 'mousemove', (e: MouseEvent) => { |
|||
this.onMouseMove(e); |
|||
}); |
|||
|
|||
this.mouseUpSubscription = |
|||
this.renderer.listenGlobal('window', 'mouseup', (e: MouseEvent) => { |
|||
this.onMouseUp(e); |
|||
}); |
|||
|
|||
this.stopEvent(event); |
|||
} |
|||
|
|||
private onMouseMove(event: MouseEvent) { |
|||
const position = new Vec2(event.clientX, event.clientY); |
|||
|
|||
if (!this.clonedElement && position.sub(this.startPosition).lengtSquared > 100) { |
|||
this.clonedElement = this.element.nativeElement.cloneNode(true); |
|||
|
|||
this.clonedElement!.style.position = 'fixed'; |
|||
this.clonedElement!.style.zIndex = '10000'; |
|||
|
|||
document.body.appendChild(this.clonedElement!); |
|||
} |
|||
|
|||
if (this.clonedElement) { |
|||
const elementPosition = position.sub(this.startOffset); |
|||
|
|||
this.clonedElement.style.left = elementPosition.x + 'px'; |
|||
this.clonedElement.style.top = elementPosition.y + 'px'; |
|||
} |
|||
|
|||
this.stopEvent(event); |
|||
} |
|||
|
|||
private onMouseUp(event: MouseEvent) { |
|||
if (this.clonedElement) { |
|||
this.clonedElement.remove(); |
|||
} |
|||
|
|||
let dropCandidate: Element | null = document.elementFromPoint(event.clientX, event.clientY); |
|||
|
|||
while (dropCandidate && (dropCandidate.classList && !dropCandidate.classList.contains('gp-drop'))) { |
|||
dropCandidate = dropCandidate.parentNode as Element; |
|||
} |
|||
|
|||
if (dropCandidate && dropCandidate.id) { |
|||
const position = this.getRelativeCoordinates(event, dropCandidate).sub(this.startOffset).round(); |
|||
|
|||
this.dragService.emitDrop({ position, model: this.model, dropTarget: dropCandidate.id }); |
|||
} |
|||
|
|||
if (this.mouseMoveSubscription) { |
|||
this.mouseMoveSubscription(); |
|||
this.mouseMoveSubscription = null; |
|||
} |
|||
|
|||
if (this.mouseUpSubscription) { |
|||
this.mouseUpSubscription(); |
|||
this.mouseUpSubscription = null; |
|||
} |
|||
|
|||
this.clonedElement = null; |
|||
|
|||
this.stopEvent(event); |
|||
} |
|||
|
|||
private stopEvent(event: Event) { |
|||
event.preventDefault(); |
|||
event.stopPropagation(); |
|||
} |
|||
|
|||
private getRelativeCoordinates(e: any, container: any): Vec2 { |
|||
const rect = container.getBoundingClientRect(); |
|||
|
|||
const x = !!e.touches ? e.touches[0].pageX : e.pageX; |
|||
const y = !!e.touches ? e.touches[0].pageY : e.pageY; |
|||
|
|||
return new Vec2(x - rect.left, y - rect.top); |
|||
} |
|||
} |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"focus-on-change.directive.js","sourceRoot":"","sources":["focus-on-change.directive.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;;;;;;;;;;AAEH,IAAY,GAAG,WAAM,eAAe,CAAC,CAAA;AAKrC;IAII,gCACY,QAAmB,EAAE,GAAG,EAAC,UAAU,EACnC,QAAiB,EAAE,GAAG,EAAC,QAAQ;QADvC,wBAA2B,GAA3B,qBAA2B;QAC3B,wBAAyB,GAAzB,mBAAyB;QADjB,aAAQ,GAAR,QAAQ,CAAW;QACnB,aAAQ,GAAR,QAAQ,CAAS;IAE7B,CAAC;IAEM,4CAAW,GAAlB,UAAmB,OAA4C;QAA/D,iBAIC;QAHG,UAAU,CAAC;YACP,KAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,KAAI,CAAC,UAAU,CAAC,aAAa,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;QAClF,CAAC,EAAE,GAAG,CAAC,CAAC;IACZ,CAAC;IAbD;QAAC,GAAG,CAAC,KAAK,EAAE;;mEAAA;IAJhB;QAAC,GAAG,CAAC,SAAS,CAAC;YACX,QAAQ,EAAE,mBAAmB;SAChC,CAAC;;8BAAA;IAgBF,6BAAC;AAAD,CAAC,AAfD,IAeC;AAfY,8BAAsB,yBAelC,CAAA"} |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"focus-on-change.directive.spec.js","sourceRoot":"","sources":["focus-on-change.directive.spec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAIH,0CAAuC,6BAA6B,CAAC,CAAA;AAErE,QAAQ,CAAC,wBAAwB,EAAE;IAC/B,IAAI,eAAe,GAAG,CAAC,CAAC;IAExB,UAAU,CAAC;QACP,eAAe,GAAG,OAAO,CAAC,wBAAwB,CAAC;QAEnD,OAAO,CAAC,wBAAwB,GAAG,GAAG,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,UAAC,IAAS;QAC5D,IAAI,YAAiB,CAAC;QACtB,IAAI,aAAkB,CAAC;QAEvB,IAAM,QAAQ,GAAG;YACb,mBAAmB,EAAE,UAAC,OAAY,EAAE,MAAW,EAAE,IAAS;gBACtD,aAAa,GAAG,OAAO,CAAC;gBACxB,YAAY,GAAG,MAAM,CAAC;YAC1B,CAAC;SACJ,CAAC;QAEF,IAAM,OAAO,GAAmB;YAC5B,aAAa,EAAE,EAAE;SACpB,CAAC;QAEF,IAAI,kDAAsB,CAAC,OAAO,EAAE,QAAwB,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAE9E,MAAM,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;QACvC,MAAM,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;QAExC,UAAU,CAAC;YACP,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACnC,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;YAElD,IAAI,EAAE,CAAC;QACX,CAAC,EAAE,GAAG,CAAC,CAAC;IACZ,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC;QACN,OAAO,CAAC,wBAAwB,GAAG,eAAe,CAAC;IACvD,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} |
|||
@ -0,0 +1,52 @@ |
|||
/* |
|||
* Athene Requirements Center |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
import { FocusOnChangeDirective } from './focus-on-change.directive'; |
|||
|
|||
describe('FocusOnChangeDirective', () => { |
|||
let originalTimeout = 0; |
|||
|
|||
beforeEach(() => { |
|||
originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; |
|||
|
|||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 800; |
|||
}); |
|||
|
|||
it('should call focus on element when value changes', (done: any) => { |
|||
let calledMethod: any; |
|||
let calledElement: any; |
|||
|
|||
const renderer = { |
|||
invokeElementMethod: (element: any, method: any, args: any) => { |
|||
calledElement = element; |
|||
calledMethod = method; |
|||
} |
|||
}; |
|||
|
|||
const element: Ng2.ElementRef = { |
|||
nativeElement: {} |
|||
}; |
|||
|
|||
new FocusOnChangeDirective(element, renderer as Ng2.Renderer).ngOnChanges({}); |
|||
|
|||
expect(calledMethod).not.toBeDefined(); |
|||
expect(calledElement).not.toBeDefined(); |
|||
|
|||
setTimeout(() => { |
|||
expect(calledMethod).toBe('focus'); |
|||
expect(calledElement).toBe(element.nativeElement); |
|||
|
|||
done(); |
|||
}, 400); |
|||
}); |
|||
|
|||
afterEach(() => { |
|||
jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout; |
|||
}); |
|||
}); |
|||
@ -0,0 +1,28 @@ |
|||
/* |
|||
* Athene Requirements Center |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
@Ng2.Directive({ |
|||
selector: '[gpFocusOnChange]' |
|||
}) |
|||
export class FocusOnChangeDirective implements Ng2.OnChanges { |
|||
@Ng2.Input() |
|||
public gpFocusOnChange: any; |
|||
|
|||
constructor( |
|||
private readonly elementRef: Ng2.ElementRef, |
|||
private readonly renderer: Ng2.Renderer |
|||
) { |
|||
} |
|||
|
|||
public ngOnChanges(changes: { [key: string]: Ng2.SimpleChange }) { |
|||
setTimeout(() => { |
|||
this.renderer.invokeElementMethod(this.elementRef.nativeElement, 'focus', []); |
|||
}, 100); |
|||
} |
|||
} |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"image-drop.directive.js","sourceRoot":"","sources":["image-drop.directive.ts"],"names":[],"mappings":"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"} |
|||
@ -0,0 +1,127 @@ |
|||
/* |
|||
* Athene Requirements Center |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
import { DragService, Vec2 } from './../'; |
|||
|
|||
@Ng2.Directive({ |
|||
selector: '.gp-image-drop' |
|||
}) |
|||
export class ImageDropDirective { |
|||
constructor( |
|||
private readonly element: Ng2.ElementRef, |
|||
private readonly renderer: Ng2.Renderer, |
|||
private readonly dragService: DragService |
|||
) { |
|||
} |
|||
|
|||
@Ng2.HostListener('dragenter', ['$event']) |
|||
public onDragEnter(event: DragDropEvent) { |
|||
this.tryStopEvent(event); |
|||
} |
|||
|
|||
@Ng2.HostListener('dragover', ['$event']) |
|||
public onDragOver(event: DragDropEvent) { |
|||
this.tryStopEvent(event); |
|||
} |
|||
|
|||
@Ng2.HostListener('drop', ['$event']) |
|||
public onDrop(event: DragDropEvent) { |
|||
const image = this.findImage(event); |
|||
|
|||
if (!image) { |
|||
return; |
|||
} |
|||
|
|||
const position = this.getRelativeCoordinates(event, this.element.nativeElement).round(); |
|||
|
|||
const reader = new FileReader(); |
|||
|
|||
reader.onload = (loadedFile: any) => { |
|||
const imageSource: string = loadedFile.target.result; |
|||
const imageElement = document.createElement('img'); |
|||
|
|||
imageElement.onload = () => { |
|||
this.dragService.emitDrop({ |
|||
position, dropTarget: this.element.nativeElement.id, model: { |
|||
sizeX: imageElement.width, |
|||
sizeY: imageElement.height, |
|||
source: imageSource |
|||
} |
|||
}); |
|||
}; |
|||
imageElement.src = imageSource; |
|||
}; |
|||
reader.readAsDataURL(image); |
|||
|
|||
this.stopEvent(event); |
|||
} |
|||
|
|||
private stopEvent(event: Event) { |
|||
event.preventDefault(); |
|||
event.stopPropagation(); |
|||
} |
|||
|
|||
private tryStopEvent(event: DragDropEvent) { |
|||
const hasFiles = this.hasFiles(event.dataTransfer.types); |
|||
|
|||
if (!hasFiles) { |
|||
return; |
|||
} |
|||
|
|||
this.stopEvent(event); |
|||
} |
|||
|
|||
private hasFiles(types: any): boolean { |
|||
if (!types) { |
|||
return false; |
|||
} |
|||
|
|||
if (isFunction(types.indexOf)) { |
|||
return types.indexOf('Files') !== -1; |
|||
} else if (isFunction(types.contains)) { |
|||
return types.contains('Files'); |
|||
} else { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
private findImage(event: DragDropEvent): File | null { |
|||
let image: File | null = null; |
|||
|
|||
for (let i = 0; i < event.dataTransfer.files.length; i++) { |
|||
const file = event.dataTransfer.files[i]; |
|||
|
|||
if (file.type.match('image.*')) { |
|||
image = file; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
return image; |
|||
} |
|||
|
|||
private getRelativeCoordinates(e: any, container: any): Vec2 { |
|||
const rect = container.getBoundingClientRect(); |
|||
|
|||
let pos = { x: 0, y: 0 }; |
|||
|
|||
pos.x = !!e.touches ? e.touches[0].pageX : e.pageX; |
|||
pos.y = !!e.touches ? e.touches[0].pageY : e.pageY; |
|||
|
|||
return new Vec2(pos.x - rect.left, pos.y - rect.top); |
|||
} |
|||
} |
|||
|
|||
function isFunction(obj: any): boolean { |
|||
return !!(obj && obj.constructor && obj.call && obj.apply); |
|||
}; |
|||
|
|||
interface DragDropEvent extends MouseEvent { |
|||
readonly dataTransfer: DataTransfer; |
|||
} |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"money.pipe.js","sourceRoot":"","sources":["money.pipe.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;;;;;;;;;;AAEH,IAAY,GAAG,WAAM,eAAe,CAAC,CAAA;AAOrC;IACI,mBACY,QAAiB,EAAE,cAAc,EACjC,QAAkB,EAAE,sBAAsB;QADlD,wBAAyB,GAAzB,mBAAyB;QACzB,wBAA0B,GAA1B,oBAA0B;QADlB,aAAQ,GAAR,QAAQ,CAAS;QACjB,aAAQ,GAAR,QAAQ,CAAU;IAE9B,CAAC;IAEM,6BAAS,GAAhB,UAAiB,KAAa,EAAE,IAAc;QAC1C,IAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QAE1C,IAAI,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,GAAG,wBAAwB,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,SAAS,CAAC;QAEjJ,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;YAC1B,MAAM,GAAG,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QACjD,CAAC;QAAC,IAAI,CAAC,CAAC;YACJ,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC;QACjD,CAAC;QAED,MAAM,CAAC,MAAM,CAAC;IAClB,CAAC;IAtBL;QAAC,GAAG,CAAC,IAAI,CAAC;YACN,IAAI,EAAE,OAAO;SAChB,CAAC;;iBAAA;IAqBF,gBAAC;AAAD,CAAC,AApBD,IAoBC;AApBY,iBAAS,YAoBrB,CAAA"} |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"money.pipe.spec.js","sourceRoot":"","sources":["money.pipe.spec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,iBAAuD,OAAO,CAAC,CAAA;AAE/D,2BAA0B,cAAc,CAAC,CAAA;AAEzC,QAAQ,CAAC,WAAW,EAAE;IAClB,EAAE,CAAC,qDAAqD,EAAE;QACtD,IAAM,IAAI,GAAG,IAAI,sBAAS,CAAC,IAAI,iBAAc,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,IAAI,yBAAsB,CAAC,GAAG,CAAC,CAAC,CAAC;QAE5F,IAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC1C,IAAM,QAAQ,GAAG,uCAAuC,CAAC;QAEzD,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qEAAqE,EAAE;QACtE,IAAM,IAAI,GAAG,IAAI,sBAAS,CAAC,IAAI,iBAAc,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,IAAI,yBAAsB,CAAC,GAAG,CAAC,CAAC,CAAC;QAE5F,IAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACzC,IAAM,QAAQ,GAAG,uCAAuC,CAAC;QAEzD,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE;QACvD,IAAM,IAAI,GAAG,IAAI,sBAAS,CAAC,IAAI,iBAAc,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,EAAE,IAAI,yBAAsB,CAAC,GAAG,CAAC,CAAC,CAAC;QAEnG,IAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC1C,IAAM,QAAQ,GAAG,uCAAuC,CAAC;QAEzD,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE;QACvE,IAAM,IAAI,GAAG,IAAI,sBAAS,CAAC,IAAI,iBAAc,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,EAAE,IAAI,yBAAsB,CAAC,GAAG,CAAC,CAAC,CAAC;QAEnG,IAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACzC,IAAM,QAAQ,GAAG,uCAAuC,CAAC;QAEzD,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} |
|||
@ -0,0 +1,48 @@ |
|||
/* |
|||
* Athene Requirements Center |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import { CurrencyConfig, DecimalSeparatorConfig } from './../'; |
|||
|
|||
import { MoneyPipe } from './money.pipe'; |
|||
|
|||
describe('MoneyPipe', () => { |
|||
it('should format money values with symbol after number', () => { |
|||
const pipe = new MoneyPipe(new CurrencyConfig('EUR', '€'), new DecimalSeparatorConfig(',')); |
|||
|
|||
const actual = pipe.transform(123.49, []); |
|||
const expected = '123,<span class="decimal">49</span> €'; |
|||
|
|||
expect(actual).toBe(expected); |
|||
}); |
|||
|
|||
it('should format money values with symbol after number and one decimal', () => { |
|||
const pipe = new MoneyPipe(new CurrencyConfig('EUR', '€'), new DecimalSeparatorConfig(',')); |
|||
|
|||
const actual = pipe.transform(123.4, []); |
|||
const expected = '123,<span class="decimal">40</span> €'; |
|||
|
|||
expect(actual).toBe(expected); |
|||
}); |
|||
|
|||
it('should format money values with symbol before number', () => { |
|||
const pipe = new MoneyPipe(new CurrencyConfig('EUR', '€', false), new DecimalSeparatorConfig(',')); |
|||
|
|||
const actual = pipe.transform(123.49, []); |
|||
const expected = '€ 123,<span class="decimal">49</span>'; |
|||
|
|||
expect(actual).toBe(expected); |
|||
}); |
|||
|
|||
it('should format money values with symbol before number and one decimal', () => { |
|||
const pipe = new MoneyPipe(new CurrencyConfig('EUR', '€', false), new DecimalSeparatorConfig(',')); |
|||
|
|||
const actual = pipe.transform(123.4, []); |
|||
const expected = '€ 123,<span class="decimal">40</span>'; |
|||
|
|||
expect(actual).toBe(expected); |
|||
}); |
|||
}); |
|||
@ -0,0 +1,37 @@ |
|||
/* |
|||
* Athene Requirements Center |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
import { CurrencyConfig, DecimalSeparatorConfig } from './../configurations'; |
|||
|
|||
@Ng2.Pipe({ |
|||
name: 'money' |
|||
}) |
|||
export class MoneyPipe { |
|||
constructor( |
|||
private readonly currency: CurrencyConfig, |
|||
private readonly separator: DecimalSeparatorConfig |
|||
) { |
|||
} |
|||
|
|||
public transform(value: number, args: string[]): any { |
|||
const money = value.toFixed(2).toString(); |
|||
|
|||
let result = money.substr(0, money.length - 3) + this.separator.value + '<span class="decimal">' + money.substr(money.length - 2, 2) + '</span>'; |
|||
|
|||
if (this.currency.showAfter) { |
|||
result = result + ' ' + this.currency.symbol; |
|||
} else { |
|||
result = this.currency.symbol + ' ' + result; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
|
|||
|
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"shortcut.component.js","sourceRoot":"","sources":["shortcut.component.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;;;;;;;;;;AAEH,IAAY,GAAG,WAAM,eAAe,CAAC,CAAA;AAQrC;IAYI,2BACY,QAAwB,EAAE,eAAe,EACzC,QAAa,EAAE,GAAG,EAAC,MAAM;QADjC,wBAAgC,GAAhC,0BAAgC;QAChC,wBAAqB,GAArB,eAAqB;QADb,aAAQ,GAAR,QAAQ,CAAgB;QACxB,aAAQ,GAAR,QAAQ,CAAK;QANlB,YAAO,GAAG,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;IAQxC,CAAC;IAEM,oCAAQ,GAAf;QAAA,iBAcC;QAbG,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;QAE1B,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YAChB,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAA,CAAC;gBACpC,EAAE,CAAC,CAAC,CAAC,KAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;oBACjB,KAAI,CAAC,IAAI,CAAC,GAAG,CAAC;wBACV,KAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;oBACzB,CAAC,CAAC,CAAC;gBACP,CAAC;gBAED,MAAM,CAAC,KAAK,CAAC;YACjB,CAAC,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IACM,uCAAW,GAAlB;QACI,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YAChB,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5C,CAAC;IACL,CAAC;IApCD;QAAC,GAAG,CAAC,KAAK,EAAE;;mDAAA;IAGZ;QAAC,GAAG,CAAC,KAAK,EAAE;;uDAAA;IAGZ;QAAC,GAAG,CAAC,MAAM,EAAE;;sDAAA;IAXjB;QAAC,GAAG,CAAC,SAAS,CAAC;YACX,QAAQ,EAAE,aAAa;YACvB,QAAQ,EAAE,EAAE;SACf,CAAC;;yBAAA;IAuCF,wBAAC;AAAD,CAAC,AAtCD,IAsCC;AAtCY,yBAAiB,oBAsC7B,CAAA"} |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"shortcut.component.spec.js","sourceRoot":"","sources":["shortcut.component.spec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,IAAY,GAAG,WAAM,eAAe,CAAC,CAAA;AAErC,iBAAqC,OAAO,CAAC,CAAA;AAC7C,mCAAqC,sBAAsB,CAAC,CAAA;AAE5D,QAAQ,CAAC,mBAAmB,EAAE;IAC1B,IAAI,eAAgC,CAAC;IAErC,UAAU,CAAC;QACP,eAAe,GAAG,IAAI,kBAAe,EAAE,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oBAAoB,EAAE;QACrB,IAAM,iBAAiB,GAAG,IAAI,sCAAiB,CAAC,eAAe,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAErF,MAAM,CAAC,iBAAiB,CAAC,CAAC,WAAW,EAAE,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0BAA0B,EAAE;QAC3B,IAAM,iBAAiB,GAAG,IAAI,sCAAiB,CAAC,eAAe,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAErF,iBAAiB,CAAC,IAAI,GAAG,IAAI,CAAA;QAAA,CAAC,CAAC;QAC/B,iBAAiB,CAAC,QAAQ,EAAE,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE;QAC9B,IAAM,iBAAiB,GAAG,IAAI,sCAAiB,CAAC,eAAe,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAErF,iBAAiB,CAAC,IAAI,GAAG,IAAI,CAAA;QAAA,CAAC,CAAC;QAC/B,iBAAiB,CAAC,WAAW,EAAE,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE;QACpC,IAAM,iBAAiB,GAAG,IAAI,sCAAiB,CAAC,eAAe,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAErF,IAAI,WAAW,GAAG,KAAK,CAAC;QAExB,iBAAiB,CAAC,IAAI,GAAG,QAAQ,CAAC;QAClC,iBAAiB,CAAC,QAAQ,EAAE,CAAC;QAC7B,iBAAiB,CAAC,OAAO,CAAC,SAAS,CAAC,cAAQ,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAEnE,eAAe,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAElC,MAAM,CAAC,WAAW,CAAC,CAAC,UAAU,EAAE,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE;QACrD,IAAM,iBAAiB,GAAG,IAAI,sCAAiB,CAAC,eAAe,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAErF,IAAI,WAAW,GAAG,KAAK,CAAC;QAExB,iBAAiB,CAAC,IAAI,GAAG,QAAQ,CAAC;QAClC,iBAAiB,CAAC,QAAQ,EAAE,CAAC;QAC7B,iBAAiB,CAAC,OAAO,CAAC,SAAS,CAAC,cAAQ,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACnE,iBAAiB,CAAC,QAAQ,GAAG,IAAI,CAAC;QAElC,eAAe,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAElC,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,EAAE,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE;QACtD,IAAM,iBAAiB,GAAG,IAAI,sCAAiB,CAAC,eAAe,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAErF,IAAI,WAAW,GAAG,KAAK,CAAC;QAExB,iBAAiB,CAAC,IAAI,GAAG,QAAQ,CAAC;QAClC,iBAAiB,CAAC,QAAQ,EAAE,CAAC;QAC7B,iBAAiB,CAAC,OAAO,CAAC,SAAS,CAAC,cAAQ,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACnE,iBAAiB,CAAC,WAAW,EAAE,CAAC;QAEhC,eAAe,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAElC,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,EAAE,CAAC;IACpC,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} |
|||
@ -0,0 +1,83 @@ |
|||
/* |
|||
* Athene Requirements Center |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
import { ShortcutService } from './../'; |
|||
import { ShortcutComponent } from './shortcut.component'; |
|||
|
|||
describe('ShortcutComponent', () => { |
|||
let shortcutService: ShortcutService; |
|||
|
|||
beforeEach(() => { |
|||
shortcutService = new ShortcutService(); |
|||
}); |
|||
|
|||
it('should instantiate', () => { |
|||
const shortcutComponent = new ShortcutComponent(shortcutService, new Ng2.NgZone({})); |
|||
|
|||
expect(shortcutComponent).toBeDefined(); |
|||
}); |
|||
|
|||
it('should init without keys', () => { |
|||
const shortcutComponent = new ShortcutComponent(shortcutService, new Ng2.NgZone({})); |
|||
|
|||
shortcutComponent.keys = null!; |
|||
shortcutComponent.ngOnInit(); |
|||
}); |
|||
|
|||
it('should destroy without keys', () => { |
|||
const shortcutComponent = new ShortcutComponent(shortcutService, new Ng2.NgZone({})); |
|||
|
|||
shortcutComponent.keys = null!; |
|||
shortcutComponent.ngOnDestroy(); |
|||
}); |
|||
|
|||
it('should raise event when triggered', () => { |
|||
const shortcutComponent = new ShortcutComponent(shortcutService, new Ng2.NgZone({})); |
|||
|
|||
let isTriggered = false; |
|||
|
|||
shortcutComponent.keys = 'ctrl+a'; |
|||
shortcutComponent.ngOnInit(); |
|||
shortcutComponent.trigger.subscribe(() => { isTriggered = true; }); |
|||
|
|||
shortcutService.trigger('ctrl+a'); |
|||
|
|||
expect(isTriggered).toBeTruthy(); |
|||
}); |
|||
|
|||
it('should not raise event when triggered but disabled', () => { |
|||
const shortcutComponent = new ShortcutComponent(shortcutService, new Ng2.NgZone({})); |
|||
|
|||
let isTriggered = false; |
|||
|
|||
shortcutComponent.keys = 'ctrl+a'; |
|||
shortcutComponent.ngOnInit(); |
|||
shortcutComponent.trigger.subscribe(() => { isTriggered = true; }); |
|||
shortcutComponent.disabled = true; |
|||
|
|||
shortcutService.trigger('ctrl+a'); |
|||
|
|||
expect(isTriggered).toBeFalsy(); |
|||
}); |
|||
|
|||
it('should not raise event when triggered but destroyed', () => { |
|||
const shortcutComponent = new ShortcutComponent(shortcutService, new Ng2.NgZone({})); |
|||
|
|||
let isTriggered = false; |
|||
|
|||
shortcutComponent.keys = 'ctrl+a'; |
|||
shortcutComponent.ngOnInit(); |
|||
shortcutComponent.trigger.subscribe(() => { isTriggered = true; }); |
|||
shortcutComponent.ngOnDestroy(); |
|||
|
|||
shortcutService.trigger('ctrl+a'); |
|||
|
|||
expect(isTriggered).toBeFalsy(); |
|||
}); |
|||
}); |
|||
@ -0,0 +1,54 @@ |
|||
/* |
|||
* Athene Requirements Center |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
import { ShortcutService } from './../services/shortcut.service'; |
|||
|
|||
@Ng2.Component({ |
|||
selector: 'gp-shortcut', |
|||
template: '' |
|||
}) |
|||
export class ShortcutComponent implements Ng2.OnInit, Ng2.OnDestroy { |
|||
@Ng2.Input() |
|||
public keys: string; |
|||
|
|||
@Ng2.Input() |
|||
public disabled: boolean; |
|||
|
|||
@Ng2.Output() |
|||
public trigger = new Ng2.EventEmitter(); |
|||
|
|||
private lastKeys: string; |
|||
|
|||
constructor( |
|||
private readonly shortcutService: ShortcutService, |
|||
private readonly zone: Ng2.NgZone |
|||
) { |
|||
} |
|||
|
|||
public ngOnInit() { |
|||
this.lastKeys = this.keys; |
|||
|
|||
if (this.lastKeys) { |
|||
this.shortcutService.on(this.lastKeys, e => { |
|||
if (!this.disabled) { |
|||
this.zone.run(() => { |
|||
this.trigger.next(e); |
|||
}); |
|||
} |
|||
|
|||
return false; |
|||
}); |
|||
} |
|||
} |
|||
public ngOnDestroy() { |
|||
if (this.lastKeys) { |
|||
this.shortcutService.off(this.lastKeys); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<div class="slider-bar" #bar (click)="onBarMouseClick($event)"> |
|||
<div class="slider-thumb" #thumb (mousedown)="onThumbMouseDown($event)"></div> |
|||
</div> |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"slider.component.js","sourceRoot":"","sources":["slider.component.ts"],"names":[],"mappings":"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"} |
|||
@ -0,0 +1,37 @@ |
|||
@import '../../theme/_mixins.scss'; |
|||
|
|||
$bar-height: 12px; |
|||
|
|||
$thumb-size: 20px; |
|||
$thumb-margin: ($thumb-size - $bar-height) * 0.5; |
|||
|
|||
$color-border: #ccc; |
|||
$color-focus: #66afe9; |
|||
|
|||
.slider { |
|||
&-bar { |
|||
@include border-radius($bar-height * 0.5); |
|||
position: relative; |
|||
border: 1px solid $color-border; |
|||
margin-bottom: 20px; |
|||
margin-top: 5px; |
|||
margin-right: $thumb-size * 0.5; |
|||
background: white; |
|||
height: $bar-height; |
|||
} |
|||
|
|||
&-thumb { |
|||
@include border-radius($thumb-size * 0.5); |
|||
position: absolute; |
|||
width: $thumb-size; |
|||
height: $thumb-size; |
|||
border: 1px solid $color-border; |
|||
background: white; |
|||
margin-top: -$thumb-margin; |
|||
margin-left: -$thumb-size * 0.5; |
|||
} |
|||
|
|||
&-thumb.focused { |
|||
border-color: $color-focus; |
|||
} |
|||
} |
|||
@ -0,0 +1,145 @@ |
|||
/* |
|||
* Athene Requirements Center |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
@Ng2.Component({ |
|||
selector: 'gp-slider', |
|||
styles, |
|||
template |
|||
}) |
|||
export class SliderComponent implements Ng2.OnChanges { |
|||
private mouseMoveSubscription: Function | null; |
|||
private mouseUpSubscription: Function | null; |
|||
private centerStartOffset = 0; |
|||
private startValue: number; |
|||
|
|||
@Ng2.ViewChild('bar') |
|||
public bar: Ng2.ElementRef; |
|||
|
|||
@Ng2.ViewChild('thumb') |
|||
public thumb: Ng2.ElementRef; |
|||
|
|||
@Ng2.Input() |
|||
public min: number = 0; |
|||
|
|||
@Ng2.Input() |
|||
public max: number = 100; |
|||
|
|||
@Ng2.Input() |
|||
public value: number; |
|||
|
|||
@Ng2.Output() |
|||
public valueChange = new Ng2.EventEmitter(); |
|||
|
|||
constructor(private readonly renderer: Ng2.Renderer) { } |
|||
|
|||
public ngOnChanges(changes: Ng2.SimpleChanges) { |
|||
const relativeValue = (this.value - this.min) / (this.max - this.min); |
|||
|
|||
this.setThumbPosition(relativeValue); |
|||
} |
|||
|
|||
public onBarMouseClick(event: MouseEvent) { |
|||
const relativeValue = this.getRelativeX(event); |
|||
|
|||
this.setThumbPosition(relativeValue); |
|||
|
|||
const newValue = Math.round(relativeValue * (this.max - this.min) + this.min); |
|||
|
|||
if (newValue !== this.value) { |
|||
this.valueChange.emit(newValue); |
|||
} |
|||
|
|||
this.stopEvent(event); |
|||
} |
|||
|
|||
public onThumbMouseDown(event: MouseEvent) { |
|||
this.centerStartOffset = event.offsetX - this.thumb.nativeElement.clientWidth * 0.5; |
|||
|
|||
this.startValue = this.value; |
|||
|
|||
this.mouseMoveSubscription = |
|||
this.renderer.listenGlobal('window', 'mousemove', (e: MouseEvent) => { |
|||
this.onMouseMove(e); |
|||
}); |
|||
|
|||
this.mouseUpSubscription = |
|||
this.renderer.listenGlobal('window', 'mouseup', (e: MouseEvent) => { |
|||
this.onMouseUp(e); |
|||
}); |
|||
|
|||
this.renderer.setElementClass(this.thumb.nativeElement, 'focused', true); |
|||
|
|||
this.stopEvent(event); |
|||
} |
|||
|
|||
private onMouseMove(event: MouseEvent) { |
|||
const relativeValue = this.getRelativeX(event); |
|||
|
|||
this.setThumbPosition(relativeValue); |
|||
|
|||
this.stopEvent(event); |
|||
} |
|||
|
|||
private onMouseUp(event: MouseEvent) { |
|||
const relativeValue = this.getRelativeX(event); |
|||
|
|||
const newValue = Math.round(relativeValue * (this.max - this.min) + this.min); |
|||
|
|||
if (newValue !== this.startValue) { |
|||
this.valueChange.emit(newValue); |
|||
} |
|||
|
|||
this.releaseMouseHandlers(); |
|||
this.renderer.setElementClass(this.thumb.nativeElement, 'focused', false); |
|||
|
|||
this.centerStartOffset = 0; |
|||
|
|||
this.stopEvent(event); |
|||
} |
|||
|
|||
private getRelativeX(event: MouseEvent): number { |
|||
const parentOffsetX = this.getParentX(event, this.bar.nativeElement) - this.centerStartOffset; |
|||
const parentWidth = this.bar.nativeElement.clientWidth; |
|||
|
|||
const relativeValue = Math.min(1, Math.max(0, (parentOffsetX - this.centerStartOffset) / parentWidth)); |
|||
|
|||
return relativeValue; |
|||
} |
|||
|
|||
private getParentX(e: any, container: any): number { |
|||
const rect = container.getBoundingClientRect(); |
|||
|
|||
const x = !!e.touches ? e.touches[0].pageX : e.pageX; |
|||
|
|||
return x - rect.left; |
|||
} |
|||
|
|||
private setThumbPosition(relativeValue: number) { |
|||
relativeValue = Math.min(1, Math.max(0, relativeValue)); |
|||
|
|||
this.renderer.setElementStyle(this.thumb.nativeElement, 'left', relativeValue * 100 + '%'); |
|||
} |
|||
|
|||
private stopEvent(event: Event) { |
|||
event.preventDefault(); |
|||
event.stopPropagation(); |
|||
} |
|||
|
|||
private releaseMouseHandlers() { |
|||
if (this.mouseMoveSubscription) { |
|||
this.mouseMoveSubscription(); |
|||
this.mouseMoveSubscription = null; |
|||
} |
|||
|
|||
if (this.mouseUpSubscription) { |
|||
this.mouseUpSubscription(); |
|||
this.mouseUpSubscription = null; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"spinner.component.js","sourceRoot":"","sources":["spinner.component.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;;;;;;;;;;AAEH,IAAY,GAAG,WAAM,eAAe,CAAC,CAAA;AAQrC;IACI,0BAAY,OAAuB;QAC/B,IAAM,aAAa,GAAG;YAClB,KAAK,EAAE,EAAE;YACT,MAAM,EAAE,CAAC;YACT,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,CAAC;YACT,OAAO,EAAE,CAAC;YACV,MAAM,EAAE,CAAC;YACT,SAAS,EAAE,CAAC;YACZ,KAAK,EAAE,MAAM;YACb,KAAK,EAAE,GAAG;YACV,KAAK,EAAE,EAAE;YACT,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,KAAK;YACd,SAAS,EAAE,SAAS;YACpB,MAAM,EAAE,CAAC;YACT,QAAQ,EAAE,UAAU;SACvB,CAAC;QAEF,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QAEtD,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IAC3D,CAAC;IA3BL;QAAC,GAAG,CAAC,SAAS,CAAC;YACX,QAAQ,EAAE,YAAY;YACtB,QAAQ,EAAE,EAAE;SACf,CAAC;6CAE2B,UAAU;wBAFrC;IAyBF,uBAAC;AAAD,CAAC,AAxBD,IAwBC;AAxBY,wBAAgB,mBAwB5B,CAAA"} |
|||
@ -0,0 +1,40 @@ |
|||
/* |
|||
* Athene Requirements Center |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
declare var Spinner: any; |
|||
|
|||
@Ng2.Component({ |
|||
selector: 'gp-spinner', |
|||
template: '' |
|||
}) |
|||
export class SpinnerComponent { |
|||
constructor(element: Ng2.ElementRef) { |
|||
const mediumOptions = { |
|||
lines: 12, |
|||
length: 5, |
|||
width: 2, |
|||
radius: 6, |
|||
corners: 1, |
|||
rotate: 0, |
|||
direction: 1, |
|||
color: '#000', |
|||
speed: 1.5, |
|||
trail: 40, |
|||
shadow: false, |
|||
hwaccel: false, |
|||
className: 'spinner', |
|||
zIndex: 0, |
|||
position: 'relative' |
|||
}; |
|||
|
|||
element.nativeElement.classList.add('spinner-medium'); |
|||
|
|||
new Spinner(mediumOptions).spin(element.nativeElement); |
|||
} |
|||
} |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"user-report.component.js","sourceRoot":"","sources":["user-report.component.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;;;;;;;;;;AAEH,IAAY,GAAG,WAAM,eAAe,CAAC,CAAA;AAErC,+BAAiC,qBAAqB,CAAC,CAAA;AAMvD;IACI,6BAAY,MAAwB,EACxB,QAAiB,EAAE,GAAG,EAAC,QAAQ;QAAvC,wBAAyB,GAAzB,mBAAyB;QAAjB,aAAQ,GAAR,QAAQ,CAAS;QAEzB,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACtC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IACrD,CAAC;IAEM,sCAAQ,GAAf;QACI,UAAU,CAAC;YACP,IAAM,GAAG,GAAG,0CAA0C,CAAC;YAEvD,IAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YAChD,MAAM,CAAC,GAAG,GAAG,GAAG,CAAC;YACjB,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC;YAEpB,IAAM,IAAI,GAAG,QAAQ,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;YAExD,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC/C,CAAC,EAAE,IAAI,CAAC,CAAC;IACb,CAAC;IAxBL;QAAC,GAAG,CAAC,SAAS,CAAC;YACX,QAAQ,EAAE,gBAAgB;YAC1B,QAAQ,EAAE,EAAE;SACf,CAAC;;2BAAA;IAsBF,0BAAC;AAAD,CAAC,AArBD,IAqBC;AArBY,2BAAmB,sBAqB/B,CAAA"} |
|||
@ -0,0 +1,37 @@ |
|||
/* |
|||
* Athene Requirements Center |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
import { UserReportConfig } from './../configurations'; |
|||
|
|||
@Ng2.Component({ |
|||
selector: 'gp-user-report', |
|||
template: '' |
|||
}) |
|||
export class UserReportComponent implements Ng2.OnInit { |
|||
constructor(config: UserReportConfig, |
|||
private readonly renderer: Ng2.Renderer |
|||
) { |
|||
window['_urq'] = window['_urq'] || []; |
|||
window['_urq'].push(['initSite', config.siteId]); |
|||
} |
|||
|
|||
public ngOnInit() { |
|||
setTimeout(() => { |
|||
const url = 'https://cdn.userreport.com/userreport.js'; |
|||
|
|||
const script = document.createElement('script'); |
|||
script.src = url; |
|||
script.async = true; |
|||
|
|||
const node = document.getElementsByTagName('script')[0]; |
|||
|
|||
node.parentNode.insertBefore(script, node); |
|||
}, 4000); |
|||
} |
|||
} |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"validators.js","sourceRoot":"","sources":["validators.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAIH;IAAA;IAgBA,CAAC;IAfiB,kBAAO,GAArB,UAAsB,QAAgB,EAAE,QAAgB;QACpD,MAAM,CAAC,UAAC,OAAiC;YACrC,IAAI,CAAC,GAAW,OAAO,CAAC,KAAK,CAAC;YAE9B,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACxB,MAAM,CAAC,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC;YACpC,CAAC;YAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;gBACtB,MAAM,CAAC,EAAE,UAAU,EAAE,EAAE,eAAe,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3E,CAAC;YAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;gBACtB,MAAM,CAAC,EAAE,UAAU,EAAE,EAAE,eAAe,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3E,CAAC;YAED,MAAM,CAAC,EAAE,CAAC;QACd,CAAC,CAAC;IACN,CAAC;IACL,iBAAC;AAAD,CAAC,AAhBD,IAgBC;AAhBY,kBAAU,aAgBtB,CAAA"} |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"validators.spec.js","sourceRoot":"","sources":["validators.spec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,IAAY,QAAQ,WAAM,gBAAgB,CAAC,CAAA;AAE3C,iBAA2B,OAAO,CAAC,CAAA;AAEnC,QAAQ,CAAC,YAAY,EAAE;IACnB,IAAI,eAAoB,CAAC;IAEzB,UAAU,CAAC;QACP,eAAe,GAAG,aAAU,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE;QACxC,IAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAE/C,IAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QAErC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,SAAS,EAAE,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE;QACnD,IAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QAE1C,IAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QAErC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE;QACtD,IAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAE5C,IAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QAErC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE;QAChD,IAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAE3C,IAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QAErC,MAAM,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;IAChC,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} |
|||
@ -0,0 +1,50 @@ |
|||
/* |
|||
* Athene Requirements Center |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2Forms from '@angular/forms'; |
|||
|
|||
import { Validators } from './../'; |
|||
|
|||
describe('Validators', () => { |
|||
let validateBetween: any; |
|||
|
|||
beforeEach(() => { |
|||
validateBetween = Validators.between(10, 200); |
|||
}); |
|||
|
|||
it('should return error when not a number', () => { |
|||
const input = new Ng2Forms.FormControl('text'); |
|||
|
|||
const error = validateBetween(input); |
|||
|
|||
expect(error.validNumber).toBeFalsy(); |
|||
}); |
|||
|
|||
it('should return error if less than minimum setting', () => { |
|||
const input = new Ng2Forms.FormControl(5); |
|||
|
|||
const error = validateBetween(input); |
|||
|
|||
expect(error.minValue).toBeDefined(); |
|||
}); |
|||
|
|||
it('should return error if greater than maximum setting', () => { |
|||
const input = new Ng2Forms.FormControl(300); |
|||
|
|||
const error = validateBetween(input); |
|||
|
|||
expect(error.maxValue).toBeDefined(); |
|||
}); |
|||
|
|||
it('should return empty value when value is valid', () => { |
|||
const input = new Ng2Forms.FormControl(50); |
|||
|
|||
const error = validateBetween(input); |
|||
|
|||
expect(error).toBeDefined(); |
|||
}); |
|||
}); |
|||
@ -0,0 +1,26 @@ |
|||
/* |
|||
* Athene Requirements Center |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2Forms from '@angular/forms'; |
|||
|
|||
export class Validators { |
|||
public static between(minValue: number, maxValue: number) { |
|||
return (control: Ng2Forms.AbstractControl): { [key: string]: any } => { |
|||
let n: number = control.value; |
|||
|
|||
if (typeof n !== 'number') { |
|||
return { 'validNumber': false }; |
|||
} else if (n < minValue) { |
|||
return { 'minValue': { 'requiredValue': minValue, 'actualValue': n } }; |
|||
} else if (n > maxValue) { |
|||
return { 'maxValue': { 'requiredValue': maxValue, 'actualValue': n } }; |
|||
} |
|||
|
|||
return {}; |
|||
}; |
|||
} |
|||
} |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"configurations.js","sourceRoot":"","sources":["configurations.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH;IACI,sBAAmB,QAAc,EAAE,MAAM;QAA7B,wBAAqB,GAArB,gBAAqB;QAAd,aAAQ,GAAR,QAAQ,CAAM;IAAY,CAAC;IAClD,mBAAC;AAAD,CAAC,AAFD,IAEC;AAFY,oBAAY,eAExB,CAAA;AAED;IACI,gCAAmB,QAAc,EAAE,MAAM;QAA7B,wBAAqB,GAArB,gBAAqB;QAAd,aAAQ,GAAR,QAAQ,CAAM;IAAY,CAAC;IAClD,6BAAC;AAAD,CAAC,AAFD,IAEC;AAFY,8BAAsB,yBAElC,CAAA;AAED;IACI,8BAAmB,QAAyB,EAAE,OAAO;QAAzC,wBAAgC,GAAhC,2BAAgC;QAAzB,aAAQ,GAAR,QAAQ,CAAiB;IAAa,CAAC;IAC9D,2BAAC;AAAD,CAAC,AAFD,IAEC;AAFY,4BAAoB,uBAEhC,CAAA;AAED;IACI,0BAAmB,QAAe,EAAE,MAAM;QAA9B,wBAAsB,GAAtB,iBAAsB;QAAf,aAAQ,GAAR,QAAQ,CAAO;IAAY,CAAC;IACnD,uBAAC;AAAD,CAAC,AAFD,IAEC;AAFY,wBAAgB,mBAE5B,CAAA;AAED;IACI,wBACW,QAAa,EAAE,MAAM,EACrB,QAAe,EAAE,MAAM,EACvB,QAAyB;QAFhC,wBAAoB,GAApB,eAAoB;QACpB,wBAAsB,GAAtB,iBAAsB;QACtB,wBAAgC,GAAhC,WAAgB,SAAS,GAAG,IAAI;QAFzB,aAAQ,GAAR,QAAQ,CAAK;QACb,aAAQ,GAAR,QAAQ,CAAO;QACf,aAAQ,GAAR,QAAQ,CAAiB;IAEpC,CAAC;IACL,qBAAC;AAAD,CAAC,AAPD,IAOC;AAPY,sBAAc,iBAO1B,CAAA"} |
|||
@ -0,0 +1,31 @@ |
|||
/* |
|||
* Athene Requirements Center |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
export class ApiUrlConfig { |
|||
constructor(public readonly value: string) { } |
|||
} |
|||
|
|||
export class DecimalSeparatorConfig { |
|||
constructor(public readonly value: string) { } |
|||
} |
|||
|
|||
export class ProductionModeConfig { |
|||
constructor(public readonly isProductionMode: boolean) { } |
|||
} |
|||
|
|||
export class UserReportConfig { |
|||
constructor(public readonly siteId: string) { } |
|||
} |
|||
|
|||
export class CurrencyConfig { |
|||
constructor( |
|||
public readonly code: string, |
|||
public readonly symbol: string, |
|||
public readonly showAfter = true |
|||
) { |
|||
} |
|||
} |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;;;;AAEH,iBAAc,kBAAkB,CAAC,EAAA;AACjC,iBAAc,sBAAsB,CAAC,EAAA;AACrC,iBAAc,kBAAkB,CAAC,EAAA;AACjC,iBAAc,aAAa,CAAC,EAAA;AAC5B,iBAAc,8BAA8B,CAAC,EAAA;AAC7C,iBAAc,yBAAyB,CAAC,EAAA;AACxC,iBAAc,gCAAgC,CAAC,EAAA;AAC/C,iBAAc,6BAA6B,CAAC,EAAA;AAC5C,iBAAc,0BAA0B,CAAC,EAAA;AACzC,iBAAc,eAAe,CAAC,EAAA;AAC9B,iBAAc,uBAAuB,CAAC,EAAA;AACtC,iBAAc,qBAAqB,CAAC,EAAA;AACpC,iBAAc,mBAAmB,CAAC,EAAA;AAClC,iBAAc,kBAAkB,CAAC,EAAA;AACjC,iBAAc,0BAA0B,CAAC,EAAA;AACzC,iBAAc,wBAAwB,CAAC,EAAA;AACvC,iBAAc,0BAA0B,CAAC,EAAA;AACzC,iBAAc,uBAAuB,CAAC,EAAA;AACtC,iBAAc,qBAAqB,CAAC,EAAA;AACpC,iBAAc,kBAAkB,CAAC,EAAA;AACjC,iBAAc,cAAc,CAAC,EAAA;AAC7B,iBAAc,eAAe,CAAC,EAAA"} |
|||
@ -0,0 +1,29 @@ |
|||
/* |
|||
* Athene Requirements Center |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
export * from './angular/action'; |
|||
export * from './angular/validators'; |
|||
export * from './configurations'; |
|||
export * from './plattform'; |
|||
export * from './services/clipboard.service'; |
|||
export * from './services/drag.service'; |
|||
export * from './services/local-store.service'; |
|||
export * from './services/shortcut.service'; |
|||
export * from './services/title.service'; |
|||
export * from './utils/color'; |
|||
export * from './utils/color-palette'; |
|||
export * from './utils/date-helper'; |
|||
export * from './utils/date-time'; |
|||
export * from './utils/duration'; |
|||
export * from './utils/immutable-id-map'; |
|||
export * from './utils/immutable-list'; |
|||
export * from './utils/immutable-object'; |
|||
export * from './utils/immutable-set'; |
|||
export * from './utils/math-helper'; |
|||
export * from './utils/rotation'; |
|||
export * from './utils/vec2'; |
|||
export * from './utils/rect2'; |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"plattform.js","sourceRoot":"","sources":["plattform.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAIH;IAAA;IAIA,CAAC;IAAD,eAAC;AAAD,CAAC,AAJD,IAIC;AAJqB,gBAAQ,WAI7B,CAAA"} |
|||
@ -0,0 +1,14 @@ |
|||
/* |
|||
* Athene Requirements Center |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import { Observable } from 'rxjs/Observable'; |
|||
|
|||
export abstract class AppStore { |
|||
public abstract select<T>(pathOrMapFn: any, ...paths: string[]): Observable<T>; |
|||
|
|||
public abstract next(action: any): void; |
|||
} |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"clipboard.service.js","sourceRoot":"","sources":["clipboard.service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,qBAA4C,MAAM,CAAC,CAAA;AAEtC,+BAAuB,GAAG;IACnC,MAAM,CAAC,IAAI,gBAAgB,EAAE,CAAC;AAClC,CAAC,CAAC;AAEF;IAAA;QACY,iBAAY,GAAG,IAAI,sBAAe,CAAS,EAAE,CAAC,CAAC;IAmB3D,CAAC;IAjBG,sBAAW,kCAAI;aAAf;YACI,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC;QAC7B,CAAC;;;OAAA;IAEM,qCAAU,GAAjB;QACI,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,UAAA,CAAC;YACzB,MAAM,GAAG,CAAC,CAAC;QACf,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAEjB,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;IACxB,CAAC;IAEM,kCAAO,GAAd,UAAe,IAAS;QACpB,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IACL,uBAAC;AAAD,CAAC,AApBD,IAoBC;AApBY,wBAAgB,mBAoB5B,CAAA"} |
|||
@ -0,0 +1 @@ |
|||
{"version":3,"file":"clipboard.service.spec.js","sourceRoot":"","sources":["clipboard.service.spec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,iBAA0D,OAAO,CAAC,CAAA;AAElE,QAAQ,CAAC,iBAAiB,EAAE;IAExB,EAAE,CAAC,iCAAiC,EAAE;QAClC,IAAM,gBAAgB,GAAG,0BAAuB,EAAE,CAAC;QAEnD,MAAM,CAAC,gBAAgB,CAAC,CAAC,WAAW,EAAE,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oBAAoB,EAAE;QACrB,IAAM,gBAAgB,GAAG,IAAI,mBAAgB,EAAE,CAAC;QAEhD,MAAM,CAAC,gBAAgB,CAAC,CAAC,WAAW,EAAE,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE;QACnD,IAAM,gBAAgB,GAAG,IAAI,mBAAgB,EAAE,CAAC;QAEhD,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE;QAClC,IAAM,gBAAgB,GAAG,IAAI,mBAAgB,EAAE,CAAC;QAEhD,gBAAgB,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAEtC,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE;QACzC,IAAM,gBAAgB,GAAG,IAAI,mBAAgB,EAAE,CAAC;QAEhD,IAAI,IAAI,GAAG,EAAE,CAAC;QAEd,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,UAAA,CAAC;YAC7B,IAAI,GAAG,CAAC,CAAC;QACb,CAAC,CAAC,CAAC;QAEH,gBAAgB,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAEtC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} |
|||
@ -0,0 +1,51 @@ |
|||
/* |
|||
* Athene Requirements Center |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import { ClipboardService, ClipboardServiceFactory } from './../'; |
|||
|
|||
describe('ShortcutService', () => { |
|||
|
|||
it('should instantiate from factory', () => { |
|||
const clipboardService = ClipboardServiceFactory(); |
|||
|
|||
expect(clipboardService).toBeDefined(); |
|||
}); |
|||
|
|||
it('should instantiate', () => { |
|||
const clipboardService = new ClipboardService(); |
|||
|
|||
expect(clipboardService).toBeDefined(); |
|||
}); |
|||
|
|||
it('should return empty string if clipboard is empty', () => { |
|||
const clipboardService = new ClipboardService(); |
|||
|
|||
expect(clipboardService.selectText()).toBe(''); |
|||
}); |
|||
|
|||
it('should get value from clipboard', () => { |
|||
const clipboardService = new ClipboardService(); |
|||
|
|||
clipboardService.setText('MyContent'); |
|||
|
|||
expect(clipboardService.selectText()).toBe('MyContent'); |
|||
}); |
|||
|
|||
it('should raise subject when setting text', () => { |
|||
const clipboardService = new ClipboardService(); |
|||
|
|||
let text = ''; |
|||
|
|||
clipboardService.text.subscribe(t => { |
|||
text = t; |
|||
}); |
|||
|
|||
clipboardService.setText('MyContent'); |
|||
|
|||
expect(text).toBe('MyContent'); |
|||
}); |
|||
}); |
|||
@ -0,0 +1,34 @@ |
|||
/* |
|||
* Athene Requirements Center |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import { BehaviorSubject, Observable } from 'rxjs'; |
|||
|
|||
export const ClipboardServiceFactory = () => { |
|||
return new ClipboardService(); |
|||
}; |
|||
|
|||
export class ClipboardService { |
|||
private textInstance = new BehaviorSubject<string>(''); |
|||
|
|||
public get text(): Observable<string> { |
|||
return this.textInstance; |
|||
} |
|||
|
|||
public selectText(): string { |
|||
let result = ''; |
|||
|
|||
this.textInstance.subscribe(t => { |
|||
result = t; |
|||
}).unsubscribe(); |
|||
|
|||
return result || ''; |
|||
} |
|||
|
|||
public setText(text: any) { |
|||
this.textInstance.next(text); |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue