This commit is contained in:
NikolayRechkin 2019-06-11 15:01:57 +03:00
commit 999f3fb63a
29 changed files with 420 additions and 241 deletions

View File

@ -8,8 +8,13 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\web\ASC.Web.Core\ASC.Web.Core.csproj" />
<ProjectReference Include="..\ASC.Common\ASC.Common.csproj" />
<ProjectReference Include="..\ASC.Core.Common\ASC.Core.Common.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Core\" />
</ItemGroup>
</Project>

View File

@ -1,9 +0,0 @@
using System;
namespace ASC.Api.Core
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public class CustomApiAttribute : Attribute
{
}
}

View File

@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Autofac;
using Autofac.Configuration;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace ASC.Common.DependencyInjection
{
internal class AutofacComponent
{
public string Type { get; set; }
public IEnumerable<AutofacService> Services { get; set; }
}
internal class AutofacService
{
public string Type { get; set; }
}
public static class AutofacExtension
{
public static IContainer AddAutofac(this IServiceCollection services, IConfiguration configuration)
{
var sectionSettings = configuration.GetSection("components");
var cs = new List<AutofacComponent>();
sectionSettings.Bind(cs);
var currentDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
foreach (var component in cs)
{
try
{
LoadAssembly(component.Type);
foreach (var s in component.Services)
{
LoadAssembly(s.Type);
}
}
catch (System.Exception)
{
//TODO
}
}
var module = new ConfigurationModule(configuration);
var builder = new ContainerBuilder();
builder.RegisterModule(module);
var container = builder.Build();
services.AddSingleton(container);
return container;
void LoadAssembly(string type)
{
var path = Path.Combine(currentDir, type.Substring(type.IndexOf(",") + 1).Trim());
Assembly.LoadFrom($"{path}.dll");
}
}
}
}

View File

@ -785,18 +785,9 @@ namespace ASC.Common.Logging
public static class LogExtension
{
public static IServiceCollection AddLogManager(this IServiceCollection services, IConfiguration configuration)
public static IServiceCollection AddLogManager(this IServiceCollection services)
{
var module = new ConfigurationModule(configuration);
var builder = new ContainerBuilder();
builder.RegisterModule(module);
var container = builder.Build();
services.AddSingleton(container)
.AddSingleton<LogManager>();
return services;
return services.AddSingleton<LogManager>();
}
}
}

View File

@ -2,17 +2,15 @@
using System.Collections.Generic;
using System.Linq;
using ASC.Common.Utils;
using Microsoft.Extensions.DependencyInjection;
namespace ASC.Data.Storage.Configuration
{
public static class StorageConfigFactory
{
public static Storage Instance
public static IServiceCollection AddStorage(this IServiceCollection services)
{
get
{
return ConfigurationManager.GetSetting<Storage>("Storage");
}
return services.AddSingleton(r => ConfigurationManager.GetSetting<Storage>("Storage"));
}
}

View File

@ -30,8 +30,8 @@ using System.Threading.Tasks;
using Amazon;
using Amazon.S3;
using Amazon.S3.Model;
using ASC.Common.DependencyInjection;
using ASC.Core;
using ASC.Data.Storage.Configuration;
namespace ASC.Data.Storage.S3
{
@ -121,7 +121,7 @@ namespace ASC.Data.Storage.S3
{
if (!configured)
{
var config = StorageConfigFactory.Instance;
var config = CommonServiceProvider.GetService<Configuration.Storage>();
var handler = config.GetHandler("s3");
if (handler != null)
{

View File

@ -26,8 +26,6 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using ASC.Common.Caching;
@ -35,8 +33,6 @@ using ASC.Core;
using ASC.Data.Storage.Configuration;
using ASC.Core.Common.Configuration;
using ASC.Data.Storage.DiscStorage;
using Microsoft.AspNetCore.Builder;
using ASC.Common.DependencyInjection;
using Microsoft.AspNetCore.Routing;
@ -83,7 +79,7 @@ namespace ASC.Data.Storage
var store = DataStoreCache.Get(tenant, module);
if (store == null)
{
var section = StorageConfigFactory.Instance;
var section = CommonServiceProvider.GetService<Configuration.Storage>();
if (section == null)
{
throw new InvalidOperationException("config section not found");
@ -103,7 +99,7 @@ namespace ASC.Data.Storage
//Make tennant path
tenant = TennantPath.CreatePath(tenant);
var section = StorageConfigFactory.Instance;
var section = CommonServiceProvider.GetService<Configuration.Storage>();
if (section == null)
{
throw new InvalidOperationException("config section not found");
@ -116,7 +112,7 @@ namespace ASC.Data.Storage
public static IEnumerable<string> GetModuleList(string configpath, bool exceptDisabledMigration = false)
{
var section = StorageConfigFactory.Instance;
var section = CommonServiceProvider.GetService<Configuration.Storage>();
return section.Module
.Where(x => x.Visible)
.Where(x=> !exceptDisabledMigration || !x.DisableMigrate)
@ -125,7 +121,7 @@ namespace ASC.Data.Storage
public static IEnumerable<string> GetDomainList(string configpath, string modulename)
{
var section = StorageConfigFactory.Instance;
var section = CommonServiceProvider.GetService<Configuration.Storage>();
if (section == null)
{
throw new ArgumentException("config section not found");
@ -146,7 +142,7 @@ namespace ASC.Data.Storage
// throw new InvalidOperationException("Application not hosted.");
//}
var section = StorageConfigFactory.Instance;
var section = CommonServiceProvider.GetService<Configuration.Storage>();
if (section != null)
{
//old scheme
@ -224,7 +220,7 @@ namespace ASC.Data.Storage
private static IDataStore GetDataStore(string tenant, string module, DataStoreConsumer consumer, IQuotaController controller)
{
var storage = StorageConfigFactory.Instance;
var storage = CommonServiceProvider.GetService<Configuration.Storage>();
var moduleElement = storage.GetModuleElement(module);
if (moduleElement == null)
{

View File

@ -46,7 +46,7 @@ namespace ASC.Data.Storage
static WebPath()
{
var section = StorageConfigFactory.Instance;
var section = CommonServiceProvider.GetService<Configuration.Storage>();
if (section != null)
{
Appenders = section.Appender;

View File

@ -8,6 +8,10 @@
<SpaRoot>ClientApp\</SpaRoot>
<DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
<AssemblyTitle>ASC.People</AssemblyTitle>
<Company>Ascensio System SIA</Company>
<Product>ASC.People</Product>
<Copyright>(c) Ascensio System SIA. All rights reserved</Copyright>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
@ -25,8 +29,7 @@
<None Remove="$(SpaRoot)**" />
<None Include="$(SpaRoot)**" Exclude="$(SpaRoot)node_modules\**" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\common\ASC.Api.Core\ASC.Api.Core.csproj" />
<ProjectReference Include="..\..\web\ASC.Web.Core\ASC.Web.Core.csproj" />

View File

@ -1,4 +0,0 @@

using ASC.Api.Core;
[assembly: CustomApi]

View File

@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using ASC.Web.Core;
namespace ASC.People
{
public class PeopleProduct : Product
{
internal const string ProductPath = "/products/people/";
private ProductContext _context;
public static Guid ID
{
get { return new Guid("{F4D98AFD-D336-4332-8778-3C6945C81EA0}"); }
}
public override bool Visible { get { return true; } }
public override ProductContext Context
{
get { return _context; }
}
public override string Name
{
get { return "People"; }//PeopleResource.ProductName; }
}
public override string Description
{
get { return "People Description"; }//PeopleResource.ProductDescription; }
}
public override string ExtendedDescription
{
get { return "People ExtendedDescription"; }//PeopleResource.ProductDescription; }
}
public override Guid ProductID
{
get { return ID; }
}
public override string StartURL
{
get { return ProductPath; }
}
public override string HelpURL
{
get { return string.Concat(ProductPath, "help.aspx"); }
}
public override string ProductClassName
{
get { return "people"; }
}
public override void Init()
{
_context = new ProductContext
{
DisabledIconFileName = "product_disabled_logo.png",
IconFileName = "product_logo.png",
LargeIconFileName = "images/people_logolarge.png",
DefaultSortOrder = 50,
AdminOpportunities = () => new List<string>(),//PeopleResource.ProductAdminOpportunities.Split('|').ToList(),
UserOpportunities = () => new List<string>() //PeopleResource.ProductUserOpportunities.Split('|').ToList()
};
//SearchHandlerManager.Registry(new SearchHandler());
}
}
}

View File

@ -14,6 +14,7 @@
<ProjectReference Include="..\..\common\ASC.Api.Core\ASC.Api.Core.csproj" />
<ProjectReference Include="..\..\common\ASC.Common\ASC.Common.csproj" />
<ProjectReference Include="..\..\common\ASC.Core.Common\ASC.Core.Common.csproj" />
<ProjectReference Include="..\ASC.Web.Core\ASC.Web.Core.csproj" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(BuildingInsideVisualStudio)' == 'true'">

View File

@ -1,8 +1,10 @@
using System.Collections.Generic;
using ASC.Web.Api.Models;
using ASC.Web.Api.Routing;
using ASC.Web.Core;
using ASC.Web.Core.WebZones;
using Microsoft.AspNetCore.Mvc;
namespace ASC.Web.Api.Controllers
{
[DefaultRoute]
@ -13,8 +15,8 @@ namespace ASC.Web.Api.Controllers
[FormatIndexRoute()]
[FormatIndexRoute(false)]
public IEnumerable<Module> GetAll()
{
return new List<Module> {
{
var result = new List<Module>(){
new Module {
Title = "Documents",
Link = "/products/files/",
@ -37,17 +39,25 @@ namespace ASC.Web.Api.Controllers
Link = "/products/mail/",
ImageUrl = "images/mail_logolarge.png"
},
new Module {
Title = "People",
Link = "/products/people/",
ImageUrl = "images/people_logolarge.png"
},
new Module {
Title = "Community",
Link = "products/community/",
ImageUrl = "images/community_logolarge.png"
}
};
};
foreach (var a in WebItemManager.Instance.GetItems(WebZoneType.StartProductList))
{
result.Add(new Module() {
Title = a.Name,
Description = a.Description,
ImageUrl = a.Context.LargeIconFileName,
Link = a.StartURL
});
}
return result;
}
}
}

View File

@ -1,6 +1,5 @@
using System.Linq;
using System.Reflection;
using System.IO;
using System.Collections.Generic;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
@ -12,15 +11,16 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using ASC.Api.Core;
using ASC.Common.Logging;
using ASC.Web.Api.Handlers;
using ASC.Api.Core.Middleware;
using ASC.Common.Utils;
using ASC.Core;
using ASC.Core.Common;
using ASC.Common;
using ASC.Common.DependencyInjection;
using ASC.Web.Core;
using ASC.Data.Storage.Configuration;
using Autofac;
namespace ASC.Web.Api
{
@ -55,16 +55,18 @@ namespace ASC.Web.Api
config.Filters.Add(new AuthorizeFilter(policy));
});
var assemblies = Directory.GetFiles(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "ASC*.dll")
.Select(Assembly.LoadFrom)
.Where(r => r.GetCustomAttribute<CustomApiAttribute>() != null);
var container = services.AddAutofac(Configuration);
var assemblies = container.Resolve<IEnumerable<IWebItem>>().Select(r=> r.GetType().Assembly).Distinct();
foreach (var a in assemblies)
{
builder.AddApplicationPart(a);
}
services.AddLogManager(Configuration);
services.AddLogManager()
.AddStorage()
.AddWebItemManager();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
@ -95,7 +97,8 @@ namespace ASC.Web.Api
app.InitCommonServiceProvider()
.InitConfigurationManager();
.InitConfigurationManager()
.UseWebItemManager();
}
}
}

View File

@ -7,6 +7,14 @@
"type": "ASC.Common.Logging.ILog, ASC.Common"
}
]
},
{
"type": "ASC.People.PeopleProduct, ASC.People",
"services": [
{
"type": "ASC.Web.Core.IWebItem, ASC.Web.Core"
}
]
}
]
}

View File

@ -0,0 +1,23 @@
# DropDown
## Usage
```js
import { DropDown } from 'asc-web-components';
```
#### Description
Is a dropdown with any number of action
#### Usage
```js
<DropDown opened={false}></DropDown>
```
#### Properties
| Props | Type | Required | Values | Default | Description |
| ------------------ | -------- | :------: | --------------------------- | -------------- | ----------------------------------------------------------------- |
| `opened` | `bool` | - | - | `false` | Tells when the dropdown should be opened |

View File

@ -0,0 +1,49 @@
import React from 'react'
import { action } from '@storybook/addon-actions';
import { storiesOf } from '@storybook/react'
import withReadme from 'storybook-readme/with-readme'
import Readme from './README.md'
import { Container, Row, Col } from 'reactstrap';
import { GroupButton, Button, DropDown } from 'asc-web-components'
const rowStyle = { marginTop: 8 };
storiesOf('Components| DropDown', module)
.addDecorator(withReadme(Readme))
.add('base', () => (
<Container>
<Row style={rowStyle}>
<Col>Only dropdown</Col>
<Col>With Button</Col>
</Row>
<Row style={rowStyle}>
<Col>
Used for demonstration without active button
<DropDown opened={true}>
<GroupButton text='Button 1' />
<GroupButton text='Button 2' />
<GroupButton text='Button 3' />
<GroupButton text='Button 4' />
<GroupButton text='Button 5' />
<GroupButton text='Button 6' />
<GroupButton text='Button 7' />
<GroupButton text='Button 8' />
</DropDown>
</Col>
<Col>
<GroupButton text='Dropdown demo' isDropdown={true}>
<GroupButton
text='Group button'
clickAction={() => console.log('Group button clicked')}
/>
<Button
label='Base button'
size='base'
onClick={action('Base button clicked')}
/>
</GroupButton>
</Col>
</Row>
</Container>
)
);

View File

@ -26,4 +26,5 @@ Base Button is used for a group action on a page.
| `isCheckbox` | `bool` | - | - | `false` | Tells when the button should present a checkbox state |
| `isDropdown` | `bool` | - | - | `false` | Tells when the button should present a dropdown state |
| `splitted` | `bool` | - | - | `false` | Tells when the button should present a dropdown state with button |
| `opened` | `bool` | - | - | `false` | Tells when the button should be opened by default |
| `opened` | `bool` | - | - | `false` | Tells when the button should be opened by default |
| `clickAction` | `func` | - | - | - | What the button will trigger when clicked |

View File

@ -0,0 +1,67 @@
import React from 'react'
import styled, { css } from 'styled-components'
import PropTypes from 'prop-types'
const StyledDropdown = styled.div`
position: absolute;
top: 100%;
left: 0;
z-index: 1000;
margin-top: 4px;
display: ${props => (props.isOpen || props.opened ? 'block' : 'none')};
padding: 4px;
border-radius: 4px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
background: white;
border: 1px solid #d1d1d1;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
-moz-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
-webkit-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
`;
const StyledDropdownItem = styled.button`
background: none;
border: 0;
color: #333333;
cursor: pointer;
display: block;
font-size: 12px;
line-height: 24px;
margin: 0;
padding: 0 12px;
text-decoration: none;
user-select: none;
-o-user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
white-space: nowrap;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
-webkit-user-select: none;
stroke: none;
&:hover{
background-color: #e9e9e9;
border-radius: 2px;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
}
`;
const DropDown = props => {
return (
<StyledDropdown {...props}>
{React.Children.map(props.children, (child) =>
<StyledDropdownItem
tabIndex={child.props.tabIndex || -1}
onClick={child.props.clickAction || child.props.onClick}
>
{child.props.text || child.props.label}
</StyledDropdownItem>)}
</StyledDropdown>
);
}
export default DropDown

View File

@ -2,6 +2,7 @@ import React, { useState, useEffect, useRef } from 'react'
import styled, { css } from 'styled-components'
import PropTypes from 'prop-types'
import { Icons } from '../icons'
import DropDown from '../drop-down'
const backgroundColor = '#ebebeb',
disabledBackgroundColor = '#f7f7f7',
@ -101,54 +102,6 @@ const StyledButton = styled(StyledDropdownToggle)`
`}
`;
const StyledDropdownMenu = styled.div`
position: absolute;
top: 100%;
left: 0;
z-index: 1000;
margin-top: 4px;
display: ${props => (props.isOpen || props.opened ? 'block' : 'none')};
padding: 4px;
border-radius: 4px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
background: white;
border: 1px solid #d1d1d1;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
-moz-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
-webkit-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
`;
const StyledDropdownItem = styled.button`
background: none;
border: 0;
color: #333333;
cursor: pointer;
display: block;
font-size: 12px;
line-height: 24px;
margin: 0;
padding: 0 12px;
text-decoration: none;
user-select: none;
-o-user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
white-space: nowrap;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
-webkit-user-select: none;
stroke: none;
&:hover{
background-color: #e9e9e9;
border-radius: 2px;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
}
`;
const Caret = styled(Icons.ExpanderDownIcon)`
width: 10px;
margin-left: 4px;
@ -174,10 +127,6 @@ const Caret = styled(Icons.ExpanderDownIcon)`
}
`;
const clickAction = (e) => {
console.log('Button "' + e.target.innerText + '" clicked!');
}
const useOuterClickNotifier = (onOuterClick, ref) => {
useEffect(() => {
const handleClick = (e) => !ref.current.contains(e.target) && onOuterClick(e);
@ -193,19 +142,13 @@ const useOuterClickNotifier = (onOuterClick, ref) => {
}
const GroupButton = (props) => {
const { text, children, splitted, isDropdown, isCheckbox, opened, disabled, primary } = props;
const { text, splitted, isDropdown, isCheckbox, opened, disabled, primary, clickAction } = props;
const [isOpen, toggle] = useState(opened);
const ref = useRef(null);
useOuterClickNotifier((e) => toggle(false), ref);
const dropMenu =
<StyledDropdownMenu isOpen={isOpen} {...props}>
{React.Children.map(children, (child) =>
<StyledDropdownItem onClick={clickAction}>
{child.props.text}
</StyledDropdownItem>)}
</StyledDropdownMenu>;
const dropMenu = <DropDown isOpen={isOpen} {...props}/>;
const splittedDropButton =
<>
@ -261,7 +204,8 @@ GroupButton.propTypes = {
splitted: PropTypes.bool,
isCheckbox: PropTypes.bool,
isDropdown: PropTypes.bool,
tabIndex: PropTypes.number
tabIndex: PropTypes.number,
clickAction: PropTypes.func
};
GroupButton.defaultProps = {
@ -274,7 +218,8 @@ GroupButton.defaultProps = {
splitted: false,
isCheckbox: false,
isDropdown: false,
tabIndex: -1
tabIndex: -1,
clickAction: (e) => console.log('Button "' + e.target.innerText + '" clicked!')
};
export default GroupButton

View File

@ -7,6 +7,7 @@ export { default as ModuleTile } from './components/module-tile'
export { default as Loader } from './components/loader'
export { Icons } from './components/icons'
export { default as GroupButton } from './components/group-button'
export { default as DropDown } from './components/drop-down'
export { default as TreeMenu } from './components/tree-menu'
export { default as TreeNode } from './components/tree-menu-node'

View File

@ -10,7 +10,6 @@
<ItemGroup>
<Compile Remove="Jabber\JabberServiceClient.cs" />
<Compile Remove="ModuleManagement\Module.cs" />
<Compile Remove="Product.cs" />
<Compile Remove="Utility\SearchHandlerManager.cs" />
<Compile Remove="WebZones\IRenderCustomNavigation.cs" />
</ItemGroup>

View File

@ -29,7 +29,7 @@ using ASC.Web.Core.WebZones;
namespace ASC.Web.Core
{
[WebZoneAttribute(WebZoneType.TopNavigationProductList | WebZoneType.StartProductList)]
[WebZone(WebZoneType.TopNavigationProductList | WebZoneType.StartProductList)]
public interface IProduct : IWebItem
{
Guid ProductID { get; }

View File

@ -27,12 +27,12 @@
using System;
using System.IO;
using ASC.Data.Storage;
using ASC.Web.Core.Client.HttpHandlers;
//using ASC.Web.Core.Client.HttpHandlers;
using ASC.Web.Core.WebZones;
namespace ASC.Web.Core
{
[WebZoneAttribute(WebZoneType.TopNavigationProductList | WebZoneType.StartProductList)]
[WebZone(WebZoneType.TopNavigationProductList | WebZoneType.StartProductList)]
public abstract class Product : IProduct
{
public abstract Guid ProductID { get; }
@ -61,7 +61,7 @@ namespace ASC.Web.Core
Guid IWebItem.ID { get { return ProductID; } }
public virtual ClientScriptLocalization ClientScriptLocalization { get; protected set; }
//public virtual ClientScriptLocalization ClientScriptLocalization { get; protected set; }
public string GetResourcePath(string relativePath)
{

View File

@ -1,46 +0,0 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
namespace ASC.Web.Core
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public class ProductAttribute : Attribute
{
public Type Type
{
get;
private set;
}
public ProductAttribute(Type type)
{
this.Type = type;
}
}
}

View File

@ -30,10 +30,6 @@ namespace ASC.Web.Core
{
public class ProductContext : WebItemContext
{
public string MasterPageFile { get; set; }
public string ProductHTMLOverview { get; set; }
private IProductSubscriptionManager _sunscriptionManager;
public new IProductSubscriptionManager SubscriptionManager

View File

@ -33,9 +33,12 @@ using ASC.Common;
using ASC.Common.DependencyInjection;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Web.Core.Utility;
using ASC.Web.Core.WebZones;
using Autofac;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.Extensions.DependencyInjection;
namespace ASC.Web.Core
{
@ -49,11 +52,16 @@ namespace ASC.Web.Core
public class WebItemManager
{
private static readonly ILog log = LogManager.GetLogger("ASC.Web");
private static readonly ILog log;
private readonly Dictionary<Guid, IWebItem> items = new Dictionary<Guid, IWebItem>();
private static readonly string disableItem = ConfigurationManager.AppSettings["web.disabled-items"] + ",";
private static readonly List<string> disableItem;
static WebItemManager()
{
log = LogManager.GetLogger("ASC.Web");
disableItem = (ConfigurationManager.AppSettings["web:disabled-items"] ?? "").Split(",").ToList();
}
public static Guid CommunityProductID
{
@ -105,7 +113,10 @@ namespace ASC.Web.Core
get { return new Guid("{46CFA73A-F320-46CF-8D5B-CD82E1D67F26}"); }
}
public static WebItemManager Instance { get; private set; }
private static WebItemManager instance;
public static WebItemManager Instance { get { return instance ?? (instance = CommonServiceProvider.GetService<WebItemManager>()); } }
private ApplicationPartManager ApplicationPartManager { get; }
public IContainer Container { get; }
public IWebItem this[Guid id]
{
@ -117,31 +128,23 @@ namespace ASC.Web.Core
}
}
static WebItemManager()
{
Instance = new WebItemManager();
}
private WebItemManager()
public WebItemManager(IContainer container)
{
Container = container;
}
public void LoadItems()
{
foreach (var file in GetFiles())
foreach (var webitem in Container.Resolve<IEnumerable<IWebItem>>())
{
var file = webitem.ID.ToString();
try
{
if (EnabledWebItem(file))
if (DisabledWebItem(file)) continue;
if (RegistryItem(webitem))
{
var webitems = LoadWebItem(file);
foreach (var webitem in webitems)
{
if (RegistryItem(webitem))
{
log.DebugFormat("Web item {0} loaded", webitem.Name);
}
}
log.DebugFormat("Web item {0} loaded", webitem.Name);
}
}
catch (Exception exc)
@ -165,14 +168,14 @@ namespace ASC.Web.Core
{
((IProduct)webitem).Init();
}
if (webitem is IModule)
if (webitem is IModule module)
{
//TODO
//var module = (IModule)webitem;
//if (module.Context != null && module.Context.SearchHandler != null)
//{
// SearchHandlerManager.Registry(module.Context.SearchHandler);
//}
if (module.Context != null && module.Context.SearchHandler != null)
{
//TODO
//SearchHandlerManager.Registry(module.Context.SearchHandler);
}
}
items.Add(webitem.ID, webitem);
@ -240,28 +243,23 @@ namespace ASC.Web.Core
return GetItemsAll().OfType<T>().ToList();
}
private IEnumerable<IWebItem> LoadWebItem(string file)
private bool DisabledWebItem(string name)
{
var assembly = Assembly.LoadFrom(file);
var attributes = assembly.GetCustomAttributes(typeof(ProductAttribute), false).Cast<ProductAttribute>();
return attributes.Where(r=> r != null).Select(productAttribute => (IWebItem)Activator.CreateInstance(productAttribute.Type));
return disableItem.Contains(name);
}
}
private IEnumerable<string> GetFiles()
public static class WebItemManagerExtension
{
public static IServiceCollection AddWebItemManager(this IServiceCollection services)
{
const string pattern = "ASC.Web.*.dll";
if (HttpContext.Current != null)
{
return Directory.GetFiles(Path.Combine(CommonServiceProvider.GetService<IWebHostEnvironment>().ContentRootPath, "~/bin"), pattern);
}
return Directory.GetFiles(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), pattern);
services.AddSingleton<WebItemManager>();
return services;
}
private bool EnabledWebItem(string file)
public static IApplicationBuilder UseWebItemManager(this IApplicationBuilder applicationBuilder)
{
var parts = file.Split('.');
var name = 1 < parts.Length ? parts[parts.Length - 2] + "," : string.Empty;
return disableItem.IndexOf(name, StringComparison.InvariantCultureIgnoreCase) == -1;
WebItemManager.Instance.LoadItems();
return applicationBuilder;
}
}
}

View File

@ -1,12 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Hosting;
namespace ASC.Web.Studio
{
@ -17,13 +11,16 @@ namespace ASC.Web.Studio
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureAppConfiguration((hostingContext, config) => {
config
.AddJsonFile("autofac.json")
.AddJsonFile("storage.json");
});
public static IHostBuilder CreateWebHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(w=>
{
w.UseStartup<Startup>();
})
.ConfigureAppConfiguration((hostingContext, config) => {
config
.AddJsonFile("autofac.json")
.AddJsonFile("storage.json");
});
}
}

View File

@ -2,6 +2,7 @@ using ASC.Common.DependencyInjection;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Data.Storage;
using ASC.Data.Storage.Configuration;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer;
@ -39,8 +40,11 @@ namespace ASC.Web.Studio
configuration.RootPath = "ClientApp/build";
});
services.AddAutofac(Configuration);
services.AddHttpContextAccessor()
.AddLogManager(Configuration);
.AddStorage()
.AddLogManager();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.