mirror of https://github.com/Squidex/squidex.git
126 changed files with 2958 additions and 3062 deletions
@ -0,0 +1,42 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Newtonsoft.Json; |
|||
using Squidex.Infrastructure.Json.Newtonsoft; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Contents.Json |
|||
{ |
|||
public sealed class StatusConverter : JsonConverter, ISupportedTypes |
|||
{ |
|||
public IEnumerable<Type> SupportedTypes |
|||
{ |
|||
get { yield return typeof(Status); } |
|||
} |
|||
|
|||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) |
|||
{ |
|||
writer.WriteValue(value.ToString()); |
|||
} |
|||
|
|||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) |
|||
{ |
|||
if (reader.TokenType != JsonToken.String) |
|||
{ |
|||
throw new JsonException($"Expected String, but got {reader.TokenType}."); |
|||
} |
|||
|
|||
return new Status(reader.Value.ToString()); |
|||
} |
|||
|
|||
public override bool CanConvert(Type objectType) |
|||
{ |
|||
return objectType == typeof(Status); |
|||
} |
|||
} |
|||
} |
|||
@ -1,46 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Infrastructure; |
|||
using System; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Contents |
|||
{ |
|||
public struct Status2 : IEquatable<Status2> |
|||
{ |
|||
public static readonly Status2 Published = new Status2("Published"); |
|||
|
|||
public string Name { get; } |
|||
|
|||
public Status2(string name) |
|||
{ |
|||
Guard.NotNullOrEmpty(name, nameof(name)); |
|||
|
|||
Name = name; |
|||
} |
|||
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return obj is Status2 status && Equals(status); |
|||
} |
|||
|
|||
public bool Equals(Status2 other) |
|||
{ |
|||
return Name.Equals(other.Name); |
|||
} |
|||
|
|||
public override int GetHashCode() |
|||
{ |
|||
return base.GetHashCode(); |
|||
} |
|||
|
|||
public override string ToString() |
|||
{ |
|||
return Name; |
|||
} |
|||
} |
|||
} |
|||
@ -1,37 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Contents |
|||
{ |
|||
public static class StatusFlow |
|||
{ |
|||
private static readonly Dictionary<Status, Status[]> Flow = new Dictionary<Status, Status[]> |
|||
{ |
|||
[Status.Draft] = new[] { Status.Published, Status.Archived }, |
|||
[Status.Archived] = new[] { Status.Draft }, |
|||
[Status.Published] = new[] { Status.Draft, Status.Archived } |
|||
}; |
|||
|
|||
public static bool Exists(Status status) |
|||
{ |
|||
return Flow.ContainsKey(status); |
|||
} |
|||
|
|||
public static bool CanChange(Status status, Status toStatus) |
|||
{ |
|||
return Flow.TryGetValue(status, out var state) && state.Contains(toStatus); |
|||
} |
|||
|
|||
public static IEnumerable<Status> Next(Status status) |
|||
{ |
|||
return Flow.TryGetValue(status, out var result) ? result : Enumerable.Empty<Status>(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Assets |
|||
{ |
|||
public class AssetResult |
|||
{ |
|||
public IAssetEntity Asset { get; } |
|||
|
|||
public HashSet<string> Tags { get; } |
|||
|
|||
public AssetResult(IAssetEntity asset, HashSet<string> tags) |
|||
{ |
|||
Asset = asset; |
|||
|
|||
Tags = tags; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Infrastructure.Assets; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Assets.Commands |
|||
{ |
|||
public abstract class UploadAssetCommand : AssetCommand |
|||
{ |
|||
public AssetFile File { get; set; } |
|||
|
|||
public ImageInfo ImageInfo { get; set; } |
|||
|
|||
public string FileHash { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,54 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Squidex.Domain.Apps.Core.Contents; |
|||
using Squidex.Domain.Apps.Entities.Schemas; |
|||
using Squidex.Infrastructure.Tasks; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Contents |
|||
{ |
|||
public sealed class DefaultContentWorkflow : IContentWorkflow |
|||
{ |
|||
private static readonly Status[] All = { Status.Archived, Status.Draft, Status.Published }; |
|||
|
|||
private static readonly Dictionary<Status, Status[]> Flow = new Dictionary<Status, Status[]> |
|||
{ |
|||
[Status.Draft] = new[] { Status.Archived, Status.Published }, |
|||
[Status.Archived] = new[] { Status.Draft }, |
|||
[Status.Published] = new[] { Status.Draft, Status.Archived } |
|||
}; |
|||
|
|||
public Task<Status> GetInitialStatusAsync(ISchemaEntity schema) |
|||
{ |
|||
return Task.FromResult(Status.Draft); |
|||
} |
|||
|
|||
public Task<bool> CanMoveToAsync(IContentEntity content, Status next) |
|||
{ |
|||
return Task.FromResult(Flow.TryGetValue(content.Status, out var state) && state.Contains(next)); |
|||
} |
|||
|
|||
public Task<bool> CanUpdateAsync(IContentEntity content) |
|||
{ |
|||
return Task.FromResult(content.Status != Status.Archived); |
|||
} |
|||
|
|||
public Task<Status[]> GetNextsAsync(IContentEntity content) |
|||
{ |
|||
return Task.FromResult(Flow.TryGetValue(content.Status, out var result) ? result : Array.Empty<Status>()); |
|||
} |
|||
|
|||
public Task<Status[]> GetAllAsync(ISchemaEntity schema) |
|||
{ |
|||
return Task.FromResult(All); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using GraphQL.Instrumentation; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Log; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Contents.GraphQL |
|||
{ |
|||
public static class LoggingMiddleware |
|||
{ |
|||
public static Func<FieldMiddlewareDelegate, FieldMiddlewareDelegate> Create(ISemanticLog log) |
|||
{ |
|||
Guard.NotNull(log, nameof(log)); |
|||
|
|||
return new Func<FieldMiddlewareDelegate, FieldMiddlewareDelegate>(next => |
|||
{ |
|||
return async context => |
|||
{ |
|||
try |
|||
{ |
|||
return await next(context); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
log.LogWarning(ex, w => w |
|||
.WriteProperty("action", "reolveField") |
|||
.WriteProperty("status", "failed") |
|||
.WriteProperty("field", context.FieldName)); |
|||
|
|||
throw ex; |
|||
} |
|||
}; |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -1,36 +0,0 @@ |
|||
{ |
|||
// When opening a file, `editor.tabSize` and `editor.insertSpaces` will be detected based on the file contents. |
|||
"editor.detectIndentation": false, |
|||
|
|||
// Typescript version from local package to be consistent |
|||
"typescript.tsdk": "node_modules/typescript/lib", |
|||
|
|||
// Configure glob patterns for excluding files and folders. |
|||
"files.exclude": { |
|||
"**/node_modules": true, |
|||
"**/Assets": true, |
|||
"**/artifacts": true, |
|||
"**/build": true, |
|||
"**/logs": true, |
|||
"**/out": true, |
|||
"**/obj": true, |
|||
"**/bin": true, |
|||
"**/*.lock.json": true, |
|||
"**/*.bat": true, |
|||
"**/*.sln": true, |
|||
"**/*.sln.DotSettings": true, |
|||
"**/*.user": true, |
|||
"**/*.xproj": true, |
|||
"**/*.gitattributes": true, |
|||
"appsetttings.Development.json": true, |
|||
"appsetttings.Production.json": true, |
|||
".awcache": true, |
|||
".vs:": true, |
|||
".vscode:": true |
|||
}, |
|||
|
|||
"coverage-gutters.coverageFileNames": [ |
|||
"_test-output/coverage/lcov.info" |
|||
], |
|||
"coverage-gutters.showLineCoverage": true |
|||
} |
|||
@ -1,25 +0,0 @@ |
|||
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)); |
|||
}; |
|||
|
|||
exports.removeLoaders = function (config, extensions) { |
|||
var rules = config.module.rules; |
|||
|
|||
for (var i = 0; i < rules.length; i += 1) { |
|||
var rule = rules[i]; |
|||
|
|||
for (var j = 0; j < extensions.length; j += 1) { |
|||
if (rule.test.source.indexOf(extensions[j]) >= 0) { |
|||
rules.splice(i, 1); |
|||
i--; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,35 +0,0 @@ |
|||
const webpack = require('webpack'), |
|||
webpackMerge = require('webpack-merge'), |
|||
path = require('path'), |
|||
helpers = require('./helpers'), |
|||
commonConfig = require('./webpack.config.js'); |
|||
|
|||
const plugins = { |
|||
// https://github.com/jantimon/html-webpack-plugin
|
|||
HtmlWebpackPlugin: require('html-webpack-plugin') |
|||
}; |
|||
|
|||
module.exports = webpackMerge(commonConfig, { |
|||
/** |
|||
* The entry point for the bundle. Our Angular app. |
|||
* |
|||
* See: https://webpack.js.org/configuration/entry-context/
|
|||
*/ |
|||
entry: { |
|||
'shims': './app/shims.ts', |
|||
'app': './app/app.ts' |
|||
}, |
|||
|
|||
plugins: [ |
|||
new plugins.HtmlWebpackPlugin({ |
|||
hash: true, |
|||
chunks: ['shims', 'app'], |
|||
chunksSortMode: 'manual', |
|||
template: 'wwwroot/index.html' |
|||
}), |
|||
|
|||
new plugins.HtmlWebpackPlugin({ |
|||
template: 'wwwroot/_theme.html', hash: true, chunksSortMode: 'none', filename: 'theme.html' |
|||
}) |
|||
] |
|||
}); |
|||
@ -1,68 +0,0 @@ |
|||
const webpack = require('webpack'), |
|||
webpackMerge = require('webpack-merge'), |
|||
path = require('path'), |
|||
helpers = require('./helpers'), |
|||
runConfig = require('./webpack.run.base.js'); |
|||
|
|||
const plugins = { |
|||
// https://github.com/jrparish/tslint-webpack-plugin
|
|||
TsLintPlugin: require('tslint-webpack-plugin') |
|||
}; |
|||
|
|||
module.exports = webpackMerge(runConfig, { |
|||
mode: 'development', |
|||
|
|||
devtool: '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: https://webpack.js.org/configuration/module/
|
|||
*/ |
|||
module: { |
|||
/** |
|||
* An array of Rules which are matched to requests when modules are created. |
|||
* |
|||
* See: https://webpack.js.org/configuration/module/#module-rules
|
|||
*/ |
|||
rules: [{ |
|||
test: /\.scss$/, |
|||
use: [{ |
|||
loader: 'style-loader' |
|||
}, { |
|||
loader: 'css-loader' |
|||
}, { |
|||
loader: 'sass-loader?sourceMap', options: { includePaths: [helpers.root('app', 'theme')] } |
|||
}], |
|||
include: helpers.root('app', 'theme') |
|||
}] |
|||
}, |
|||
|
|||
plugins: [ |
|||
new webpack.ContextReplacementPlugin(/\@angular(\\|\/)core(\\|\/)fesm5/, helpers.root('./src'), {}), |
|||
|
|||
new plugins.TsLintPlugin({ |
|||
files: ['./app/**/*.ts'], |
|||
/** |
|||
* Path to a configuration file. |
|||
*/ |
|||
config: helpers.root('tslint.json') |
|||
}) |
|||
], |
|||
|
|||
devServer: { |
|||
headers: { |
|||
'Access-Control-Allow-Origin': '*' |
|||
}, |
|||
historyApiFallback: true |
|||
} |
|||
}); |
|||
@ -1,137 +0,0 @@ |
|||
const webpack = require('webpack'), |
|||
webpackMerge = require('webpack-merge'), |
|||
path = require('path'), |
|||
helpers = require('./helpers'), |
|||
runConfig = require('./webpack.run.base.js'); |
|||
|
|||
const plugins = { |
|||
// https://github.com/mishoo/UglifyJS2/tree/harmony
|
|||
UglifyJsPlugin: require('uglifyjs-webpack-plugin'), |
|||
// https://www.npmjs.com/package/@ngtools/webpack
|
|||
NgToolsWebpack: require('@ngtools/webpack'), |
|||
// https://github.com/webpack-contrib/mini-css-extract-plugin
|
|||
MiniCssExtractPlugin: require('mini-css-extract-plugin'), |
|||
// https://github.com/NMFR/optimize-css-assets-webpack-plugin
|
|||
OptimizeCSSAssetsPlugin: require("optimize-css-assets-webpack-plugin"), |
|||
// https://github.com/jrparish/tslint-webpack-plugin
|
|||
TsLintPlugin: require('tslint-webpack-plugin') |
|||
}; |
|||
|
|||
helpers.removeLoaders(runConfig, ['scss', 'ts']); |
|||
|
|||
module.exports = webpackMerge(runConfig, { |
|||
mode: 'production', |
|||
|
|||
output: { |
|||
/** |
|||
* The output directory as absolute path (required). |
|||
* |
|||
* See: https://webpack.js.org/configuration/output/#output-path
|
|||
*/ |
|||
path: helpers.root('wwwroot/build/'), |
|||
|
|||
publicPath: './build/', |
|||
|
|||
/** |
|||
* Specifies the name of each output file on disk. |
|||
* |
|||
* See: https://webpack.js.org/configuration/output/#output-filename
|
|||
*/ |
|||
filename: '[name].js', |
|||
|
|||
/** |
|||
* The filename of non-entry chunks as relative path inside the output.path directory. |
|||
* |
|||
* See: https://webpack.js.org/configuration/output/#output-chunkfilename
|
|||
*/ |
|||
chunkFilename: '[id].[hash].chunk.js' |
|||
}, |
|||
|
|||
/* |
|||
* Options affecting the normal modules. |
|||
* |
|||
* See: https://webpack.js.org/configuration/module/
|
|||
*/ |
|||
module: { |
|||
/** |
|||
* An array of Rules which are matched to requests when modules are created. |
|||
* |
|||
* See: https://webpack.js.org/configuration/module/#module-rules
|
|||
*/ |
|||
rules: [{ |
|||
test: /\.scss$/, |
|||
/* |
|||
* Extract the content from a bundle to a file. |
|||
* |
|||
* See: https://github.com/webpack-contrib/extract-text-webpack-plugin
|
|||
*/ |
|||
use: [ |
|||
plugins.MiniCssExtractPlugin.loader, |
|||
{ |
|||
loader: 'css-loader' |
|||
}, { |
|||
loader: 'sass-loader' |
|||
}], |
|||
/* |
|||
* Do not include component styles. |
|||
*/ |
|||
include: helpers.root('app', 'theme'), |
|||
}, { |
|||
test: /\.scss$/, |
|||
use: [{ |
|||
loader: 'raw-loader' |
|||
}, { |
|||
loader: 'sass-loader', options: { includePaths: [helpers.root('app', 'theme')] } |
|||
}], |
|||
exclude: helpers.root('app', 'theme'), |
|||
}, { |
|||
test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/, |
|||
use: [{ |
|||
loader: '@ngtools/webpack' |
|||
}] |
|||
}] |
|||
}, |
|||
|
|||
plugins: [ |
|||
new plugins.NgToolsWebpack.AngularCompilerPlugin({ |
|||
entryModule: 'app/app.module#AppModule', |
|||
sourceMap: false, |
|||
skipSourceGeneration: false, |
|||
tsConfigPath: './tsconfig.json' |
|||
}), |
|||
|
|||
new plugins.TsLintPlugin({ |
|||
files: ['./app/**/*.ts'], |
|||
/** |
|||
* Path to a configuration file. |
|||
*/ |
|||
config: helpers.root('tslint.json'), |
|||
/** |
|||
* Wait for linting and fail the build when linting error occur. |
|||
*/ |
|||
waitForLinting: true |
|||
}) |
|||
], |
|||
|
|||
optimization: { |
|||
minimizer: [ |
|||
new plugins.UglifyJsPlugin({ |
|||
uglifyOptions: { |
|||
compress: false, |
|||
ecma: 6, |
|||
mangle: true, |
|||
output: { |
|||
comments: false |
|||
} |
|||
}, |
|||
extractComments: true |
|||
}), |
|||
|
|||
new plugins.OptimizeCSSAssetsPlugin({}) |
|||
] |
|||
}, |
|||
|
|||
performance: { |
|||
hints: false |
|||
} |
|||
}); |
|||
@ -1,37 +0,0 @@ |
|||
const webpack = require('webpack'), |
|||
webpackMerge = require('webpack-merge'), |
|||
path = require('path'), |
|||
helpers = require('./helpers'), |
|||
testConfig = require('./webpack.test.js'); |
|||
|
|||
helpers.removeLoaders(testConfig, ['ts']); |
|||
|
|||
module.exports = webpackMerge(testConfig, { |
|||
module: { |
|||
/** |
|||
* An array of Rules which are matched to requests when modules are created. |
|||
* |
|||
* See: https://webpack.js.org/configuration/module/#module-rules
|
|||
*/ |
|||
rules: [{ |
|||
test: /\.ts$/, |
|||
use: [{ |
|||
loader: 'ts-loader' |
|||
}], |
|||
include: [/\.(e2e|spec)\.ts$/], |
|||
|
|||
}, { |
|||
test: /\.ts$/, |
|||
use: [{ |
|||
loader: 'istanbul-instrumenter-loader' |
|||
}, { |
|||
loader: 'ts-loader' |
|||
}, { |
|||
loader: 'angular-router-loader' |
|||
}, { |
|||
loader: 'angular2-template-loader' |
|||
}], |
|||
exclude: [/\.(e2e|spec)\.ts$/] |
|||
}] |
|||
} |
|||
}); |
|||
@ -1,16 +0,0 @@ |
|||
const webpack = require('webpack'), |
|||
webpackMerge = require('webpack-merge'), |
|||
path = require('path'), |
|||
helpers = require('./helpers'), |
|||
commonConfig = require('./webpack.config.js'); |
|||
|
|||
module.exports = webpackMerge(commonConfig, { |
|||
mode: 'development', |
|||
|
|||
/** |
|||
* Source map for Karma from the help of karma-sourcemap-loader & karma-webpack. |
|||
* |
|||
* See: https://webpack.js.org/configuration/devtool/
|
|||
*/ |
|||
devtool: 'inline-source-map' |
|||
}); |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue