├── .dockerignore ├── .gitattributes ├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── Swift.Core ├── Cluster.cs ├── CommonResult.cs ├── CommunicationResponse.cs ├── Consul │ ├── ConsulConfigCenter.cs │ ├── ConsulKV.cs │ └── ConsulService.cs ├── Election │ ├── ConsulManagerElection.cs │ ├── IManagerElection.cs │ ├── ManagerElectCompletedEvent.cs │ ├── ManagerElectionFactory.cs │ ├── ManagerElectionManager.cs │ ├── ManagerElectionOptions.cs │ ├── ManagerElectionResult.cs │ └── ManagerElectionState.cs ├── EnumExecutableFileType.cs ├── EnumJobStatus.cs ├── EnumMemberRole.cs ├── EnumTaskStatus.cs ├── ExtensionException │ ├── JobPackageConfigExtractException.cs │ └── MemberNotFoundException.cs ├── HttpServer.cs ├── IConfigCenter.cs ├── JobBase.cs ├── JobConfig.cs ├── JobTask.cs ├── JobWrapper.cs ├── Log │ ├── LogLevel.cs │ └── LogWriter.cs ├── Manager.cs ├── Member.cs ├── MemberCommunicator.cs ├── MemberWrapper.cs ├── OS │ ├── IOSAPI.cs │ ├── Linux │ │ └── LinuxAPI.cs │ ├── OSAPIFactory.cs │ ├── OSX │ │ └── OSXAPI.cs │ └── Windows │ │ └── WindowsAPI.cs ├── PlanRunTime.cs ├── ResourceManager.cs ├── Swift.Core.csproj ├── SwiftConfiguration.cs ├── SwiftProcess.cs ├── SwiftProcessCommandLine.cs ├── SwiftProcessEventActions.cs ├── Worker.cs └── packages.config ├── Swift.DemoJob ├── DemoJob.cs ├── Swift.DemoJob.csproj ├── job.json └── packages.config ├── Swift.JobEntryPoint ├── NLog.config ├── Program.cs ├── Swift.JobEntryPoint.csproj └── Swift.JobEntryPoint.runtimeconfig.json ├── Swift.Management ├── Controllers │ ├── HomeController.cs │ └── JobController.cs ├── Dockerfile ├── Models │ └── ErrorViewModel.cs ├── Program.cs ├── Startup.cs ├── Swift.Management.csproj ├── Swift │ ├── BaseSwiftService.cs │ ├── ConsulSwiftService.cs │ └── ISwiftService.cs ├── Views │ ├── Home │ │ ├── About.cshtml │ │ ├── Contact.cshtml │ │ ├── Index.cshtml │ │ ├── JobRecords.cshtml │ │ ├── Jobs.cshtml │ │ └── Members.cshtml │ ├── Shared │ │ ├── Error.cshtml │ │ ├── _CookieConsentPartial.cshtml │ │ └── _Layout.cshtml │ ├── _ViewImports.cshtml │ └── _ViewStart.cshtml ├── appsettings.Development.json ├── appsettings.json └── wwwroot │ ├── css │ ├── site.css │ └── site.min.css │ ├── favicon.ico │ ├── images │ ├── banner1.svg │ ├── banner2.svg │ └── banner3.svg │ ├── js │ ├── site.js │ └── site.min.js │ └── lib │ ├── bootstrap-datetimepicker │ ├── css │ │ ├── bootstrap-datetimepicker.css │ │ └── bootstrap-datetimepicker.min.css │ └── js │ │ ├── bootstrap-datetimepicker.js │ │ ├── bootstrap-datetimepicker.min.js │ │ └── locales │ │ ├── bootstrap-datetimepicker.ar.js │ │ ├── bootstrap-datetimepicker.az.js │ │ ├── bootstrap-datetimepicker.bg.js │ │ ├── bootstrap-datetimepicker.bn.js │ │ ├── bootstrap-datetimepicker.ca.js │ │ ├── bootstrap-datetimepicker.cs.js │ │ ├── bootstrap-datetimepicker.da.js │ │ ├── bootstrap-datetimepicker.de.js │ │ ├── bootstrap-datetimepicker.ee.js │ │ ├── bootstrap-datetimepicker.el.js │ │ ├── bootstrap-datetimepicker.es.js │ │ ├── bootstrap-datetimepicker.fi.js │ │ ├── bootstrap-datetimepicker.fr.js │ │ ├── bootstrap-datetimepicker.he.js │ │ ├── bootstrap-datetimepicker.hr.js │ │ ├── bootstrap-datetimepicker.hu.js │ │ ├── bootstrap-datetimepicker.hy.js │ │ ├── bootstrap-datetimepicker.id.js │ │ ├── bootstrap-datetimepicker.is.js │ │ ├── bootstrap-datetimepicker.it.js │ │ ├── bootstrap-datetimepicker.ja.js │ │ ├── bootstrap-datetimepicker.ka.js │ │ ├── bootstrap-datetimepicker.ko.js │ │ ├── bootstrap-datetimepicker.lt.js │ │ ├── bootstrap-datetimepicker.lv.js │ │ ├── bootstrap-datetimepicker.ms.js │ │ ├── bootstrap-datetimepicker.nb.js │ │ ├── bootstrap-datetimepicker.nl.js │ │ ├── bootstrap-datetimepicker.no.js │ │ ├── bootstrap-datetimepicker.pl.js │ │ ├── bootstrap-datetimepicker.pt-BR.js │ │ ├── bootstrap-datetimepicker.pt.js │ │ ├── bootstrap-datetimepicker.ro.js │ │ ├── bootstrap-datetimepicker.rs-latin.js │ │ ├── bootstrap-datetimepicker.rs.js │ │ ├── bootstrap-datetimepicker.ru.js │ │ ├── bootstrap-datetimepicker.sk.js │ │ ├── bootstrap-datetimepicker.sl.js │ │ ├── bootstrap-datetimepicker.sv.js │ │ ├── bootstrap-datetimepicker.sw.js │ │ ├── bootstrap-datetimepicker.th.js │ │ ├── bootstrap-datetimepicker.tr.js │ │ ├── bootstrap-datetimepicker.ua.js │ │ ├── bootstrap-datetimepicker.uk.js │ │ ├── bootstrap-datetimepicker.zh-CN.js │ │ └── bootstrap-datetimepicker.zh-TW.js │ ├── bootstrap-fileinput │ ├── .github │ │ ├── CODE_OF_CONDUCT.md │ │ ├── CONTRIBUTING.md │ │ ├── ISSUE_TEMPLATE.md │ │ └── PULL_REQUEST_TEMPLATE.md │ ├── CHANGE.md │ ├── LICENSE.md │ ├── README.md │ ├── bower.json │ ├── composer.json │ ├── css │ │ ├── fileinput-rtl.css │ │ ├── fileinput-rtl.min.css │ │ ├── fileinput.css │ │ └── fileinput.min.css │ ├── img │ │ ├── loading-sm.gif │ │ └── loading.gif │ ├── js │ │ ├── fileinput.js │ │ ├── fileinput.min.js │ │ ├── locales │ │ │ ├── LANG.js │ │ │ ├── ar.js │ │ │ ├── az.js │ │ │ ├── bg.js │ │ │ ├── ca.js │ │ │ ├── cr.js │ │ │ ├── cs.js │ │ │ ├── da.js │ │ │ ├── de.js │ │ │ ├── el.js │ │ │ ├── es.js │ │ │ ├── et.js │ │ │ ├── fa.js │ │ │ ├── fi.js │ │ │ ├── fr.js │ │ │ ├── gl.js │ │ │ ├── he.js │ │ │ ├── hu.js │ │ │ ├── id.js │ │ │ ├── it.js │ │ │ ├── ja.js │ │ │ ├── ka.js │ │ │ ├── kr.js │ │ │ ├── kz.js │ │ │ ├── lt.js │ │ │ ├── nl.js │ │ │ ├── no.js │ │ │ ├── pl.js │ │ │ ├── pt-BR.js │ │ │ ├── pt.js │ │ │ ├── ro.js │ │ │ ├── ru.js │ │ │ ├── sk.js │ │ │ ├── sl.js │ │ │ ├── sv.js │ │ │ ├── th.js │ │ │ ├── tr.js │ │ │ ├── uk.js │ │ │ ├── uz.js │ │ │ ├── vi.js │ │ │ ├── zh-TW.js │ │ │ └── zh.js │ │ └── plugins │ │ │ ├── piexif.js │ │ │ ├── piexif.min.js │ │ │ ├── purify.js │ │ │ ├── purify.min.js │ │ │ ├── sortable.js │ │ │ └── sortable.min.js │ ├── package.json │ ├── scss │ │ ├── fileinput-rtl.scss │ │ ├── fileinput.scss │ │ └── themes │ │ │ ├── explorer-fa │ │ │ └── theme.scss │ │ │ ├── explorer-fas │ │ │ └── theme.scss │ │ │ └── explorer │ │ │ └── theme.scss │ └── themes │ │ ├── explorer-fa │ │ ├── theme.css │ │ ├── theme.js │ │ ├── theme.min.css │ │ └── theme.min.js │ │ ├── explorer-fas │ │ ├── theme.css │ │ ├── theme.js │ │ ├── theme.min.css │ │ └── theme.min.js │ │ ├── explorer │ │ ├── theme.css │ │ ├── theme.js │ │ ├── theme.min.css │ │ └── theme.min.js │ │ ├── fa │ │ ├── theme.js │ │ └── theme.min.js │ │ ├── fas │ │ ├── theme.js │ │ └── theme.min.js │ │ └── gly │ │ ├── theme.js │ │ └── theme.min.js │ ├── bootstrap │ ├── .bower.json │ ├── LICENSE │ └── dist │ │ ├── css │ │ ├── bootstrap-theme.css │ │ ├── bootstrap-theme.css.map │ │ ├── bootstrap-theme.min.css │ │ ├── bootstrap-theme.min.css.map │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ │ └── js │ │ ├── bootstrap.js │ │ ├── bootstrap.min.js │ │ └── npm.js │ ├── jquery-validation-unobtrusive │ ├── .bower.json │ ├── LICENSE.txt │ ├── jquery.validate.unobtrusive.js │ └── jquery.validate.unobtrusive.min.js │ ├── jquery-validation │ ├── .bower.json │ ├── LICENSE.md │ └── dist │ │ ├── additional-methods.js │ │ ├── additional-methods.min.js │ │ ├── jquery.validate.js │ │ └── jquery.validate.min.js │ └── jquery │ ├── .bower.json │ ├── LICENSE.txt │ └── dist │ ├── jquery.js │ ├── jquery.min.js │ └── jquery.min.map ├── Swift.sln ├── Swift ├── App.config ├── NLog.config ├── Program.cs ├── Swift.csproj ├── appsettings.json └── packages.config ├── Todo.txt ├── docker-entrypoint.sh └── sources.list /.dockerignore: -------------------------------------------------------------------------------- 1 | .dockerignore 2 | .env 3 | .git 4 | .gitignore 5 | .vs 6 | .vscode 7 | docker-compose.yml 8 | docker-compose.*.yml 9 | */bin 10 | */obj 11 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.js linguist-language=C# 2 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # 运行时基础镜像 2 | FROM mcr.microsoft.com/dotnet/aspnet:3.1 AS base 3 | WORKDIR /app 4 | 5 | # 复制sources.list 6 | COPY sources.list . 7 | 8 | # 安装Consul 9 | ENV CONSUL_VERSION=1.4.2 10 | ENV HASHICORP_RELEASES=https://releases.hashicorp.com 11 | RUN set -eux && \ 12 | rm -rf /etc/localtime && \ 13 | ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \ 14 | mv /etc/apt/sources.list /etc/apt/sources.list.bak && \ 15 | mv /app/sources.list /etc/apt/ && \ 16 | apt-get update && \ 17 | apt-get install -y wget unzip iproute iproute-doc && \ 18 | mkdir -p /tmp/build && \ 19 | cd /tmp/build && \ 20 | apkArch="$(lscpu | grep 'Architecture' | sed -e 's/^Architecture:[[:space:]]*//')" && \ 21 | case "${apkArch}" in \ 22 | aarch64) consulArch='arm64' ;; \ 23 | armhf) consulArch='arm' ;; \ 24 | x86) consulArch='386' ;; \ 25 | x86_64) consulArch='amd64' ;; \ 26 | *) echo >&2 "error: unsupported architecture: ${apkArch} (see ${HASHICORP_RELEASES}/consul/${CONSUL_VERSION}/)" && exit 1 ;; \ 27 | esac && \ 28 | wget ${HASHICORP_RELEASES}/consul/${CONSUL_VERSION}/consul_${CONSUL_VERSION}_linux_${consulArch}.zip && \ 29 | mkdir /app/consul && \ 30 | unzip -d /app/consul consul_${CONSUL_VERSION}_linux_${consulArch}.zip && \ 31 | ln -s /app/consul/consul /usr/local/bin/consul && \ 32 | cd /tmp && \ 33 | rm -rf /tmp/build && \ 34 | mkdir -p /app/consul/data && \ 35 | mkdir -p /app/consul/config && \ 36 | chown 777 /app/consul/data && \ 37 | consul version 38 | 39 | # 编译项目基础镜像 40 | FROM mcr.microsoft.com/dotnet/sdk:3.1 AS build 41 | WORKDIR /src 42 | 43 | # 复制项目主文件,还原项目依赖项 44 | #COPY Swift/Swift.csproj Swift/ 45 | #COPY Swift.Core/Swift.Core.csproj Swift.Core/ 46 | #COPY Swift.Management/Swift.Management.csproj Swift.Management/ 47 | 48 | # 复制所有项目源文件,然后发布项目 49 | COPY . . 50 | RUN dotnet restore Swift/Swift.csproj 51 | RUN dotnet restore Swift.Management/Swift.Management.csproj 52 | 53 | FROM build AS publish 54 | 55 | WORKDIR /src/Swift 56 | #RUN dotnet build --configuration Release 57 | RUN dotnet publish -c Release -o /app/swift 58 | 59 | WORKDIR /src/Swift.Management 60 | RUN dotnet publish -c Release -o /app/management 61 | 62 | # 复制发布的项目文件到运行时目录,然后生成镜像 63 | FROM base AS final 64 | WORKDIR /app 65 | COPY --from=publish /app/swift ./swift 66 | COPY --from=publish /app/management ./management 67 | 68 | # 开放端口 69 | EXPOSE 8300 8301 8301/udp 8302 8302/udp 9631 9632 70 | 71 | # 启动时执行的命令 72 | COPY docker-entrypoint.sh /usr/local/bin/ 73 | RUN chmod +x /usr/local/bin/docker-entrypoint.sh 74 | ENTRYPOINT ["docker-entrypoint.sh"] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Swift 2 | 3 | Swift是一个基于.NET Core的分布式批处理框架,支持将作业分割后分发到多台服务器并行处理,可成倍提升大量数据的处理速度。 4 | 5 | 6 | ## 原理 7 | 8 | Swift作业处理分为3步:分割作业、执行任务、合并结果。 9 | 10 | Swift由多个成员节点组成集群,成员分为Manager和Worker,Manager负责分割作业和合并结果,Worker负责执行具体的任务。Manager同时只有一个,自动选举产生,集群工作需要至少2个节点,节点数>=3才有意义。 11 | 12 | Swift通过启动子进程来处理作业,原则上可以支持各类语言开发的程序,目前仅实现了.NET Core作业的支持。 13 | 14 | Swift依赖[Consul](https://www.consul.io/)管理集群节点,每台部署了Swift节点的机器都需要部署Consul。 15 | 16 | Swift作业的元数据都保存在集中的配置中心,各个节点从配置中心拉取最新的配置用于处理作业,以及将自身的工作状态实时更新到配置中心。 17 | 18 | 19 | ## Swfit使用 20 | 21 | ### 运行环境搭建 22 | 23 | Swift基于.NET Core平台,可以运行在Windows、Linux、Mac等多种操作系统,动手能力强的同学可以在自己熟悉的环境手动部署。 24 | 25 | 不过使用docker可以快速创建一个Swift集群,省去下载、部署、配置等各种麻烦事,如果你的程序没有重度使用Consul,也可以考虑用于生产环境。 26 | 27 | #### 1、docker 28 | 29 | (1)使用解决方案中的Dockerfile生成Swift镜像: 30 | 31 | ```shell 32 | docker build -t fireflysoft/swift:latest . 33 | ``` 34 | 35 | (2)启动Swift容器: 36 | 37 | 没有Consul集群的情况下,为了方便测试,支持通过参数 -consulboot 启动Consul Agent,使之作为Consul集群的Server和Leader。 38 | 生产环境下为了数据安全,应该有专门的Consul Server节点。 39 | 40 | ```shell 41 | docker run --name swift1 -d -p 9632:9632 fireflysoft/swift:latest -cluster=test -consulboot 42 | ``` 43 | 参数 -cluster 指定了Swift集群的名称。这里同时将9632端口映射到了主机,这个是Swift管理界面程序的端口。 44 | 45 | 已经有Consul Server节点的情况下,这样启动容器: 46 | 47 | ```shell 48 | docker run --name swift2 -d fireflysoft/swift:latest -cluster=test -consuljoinip=172.17.0.2 49 | ``` 50 | 参数 -consuljoinip 指定了容器中的Consul节点要加入的Consul集群中的任意一个节点。 51 | 52 | 建议启动3个Swift容器,以方便进行测试。 53 | 54 | 55 | #### 2、手动部署 56 | 57 | (1)部署Consul 58 | 59 | 这里只是大概说下Consul的部署,具体的使用或问题请网络搜索,也欢迎加入Consul交流群讨论(234939415)。 60 | 61 | 在这里下载Consul程序包:https://www.consul.io/downloads.html 62 | 63 | 然后编写节点[配置](https://www.consul.io/docs/agent/options.html),举个例子:集群dc1的192.168.0.2节点,它是一个server节点,通过节点192.168.0.3连接到集群,集群预料有3个Server节点。 64 | 65 | ```javascript 66 | { 67 | "datacenter": "dc1", 68 | "data_dir": "/usr/local/consul/data", 69 | "node_name": "192.168.0.2", 70 | "advertise_addr": "192.168.0.2", 71 | "start_join": ["192.168.0.3"], 72 | "rejoin_after_leave": true, 73 | "server": true, 74 | "bootstrap-expect":3, 75 | "ui": true 76 | } 77 | ``` 78 | 然后使用命令启动这个节点: 79 | 80 | ```shell 81 | consul agent -config-dir ./conf 82 | ``` 83 | 测试环境1个Server节点就够了,生产环境建议启动3或5个Server节点。 84 | 85 | (2)部署Swift 86 | 87 | Swift当前有2个核心程序:节点程序(Swift)和管理界面程序(Swift.Management),前者是一个控制台程序,后者是一个Web程序。这两个程序部署起来很简单,需要注意当前机器上需要已经部署了Consul节点。 88 | 89 | 首先使用Visual Studio发布程序,然后部署到指定的目录,使用命令行启动。 90 | 91 | 启动节点程序: 92 | 93 | ```shell 94 | dotnet /app/swift/Swift.dll -c swiftcluster 95 | ``` 96 | 97 | 启动管理界面程序(只需要在其中1个机器部署即可): 98 | 99 | ```shell 100 | dotnet /app/management/Swift.Management.dll --urls "http://0.0.0.0:9632" 101 | ``` 102 | 用户可以通过管理界面查看集群节点,上传作业包,监控作业运行,下载作业结果,也可以很方便的运行作业和取消作业。 103 | 104 | Swift节点建议不要少于3个,最少2个。 105 | 106 | 107 | ### 创建作业 108 | 109 | VS解决方案中提供了一个作业的例子:Swift.DemoJob,可以参考来创建自己的作业。 110 | 111 | #### 1、编写作业 112 | 113 | 用户首先需要按照Swift的规范编写作业处理程序,作业处理程序包括三部分:分割任务、执行任务、合并任务。 114 | 这三部分对应到程序中是三个方法,Swift规定了方法的名称和输入输出类型,用户实现内部逻辑即可。 115 | 116 | #### 2、打包作业 117 | 118 | 打包作业处理程序首先需要编译程序,建议使用命令: 119 | 120 | ```shell 121 | dotnet publish -c Release 122 | ``` 123 | 然后附加一个名为job.json的作业配置文件,其中指定作业的名称、可执行文件名、计划执行时间等信息: 124 | 125 | ```shell 126 | { 127 | "Name": "DemoJob", // 作业名称 128 | "FileName": "Swift.JobEntryPoint.dll", // 作业可执行文件,目前固定为.NET Core对应入口文件,不要改动 129 | "ExeType": "dotnet", // 作业可执行文件类型,目前仅支持dotnet 130 | "JobClassName": "Swift.DemoJob.dll,Swift.DemoJob.DemoJob", // 作业所在文件和类的全名称 131 | "RunTimePlan": [ "10m" ], // 作业运行时间计划,可以指定多个 132 | "TaskExecuteTimeout": 1440, // 单个任务执行超时时间,默认1440分钟 133 | "MemberUnavailableThreshold": 10, // 节点不可用的认定阈值,默认10分钟 134 | "JobSplitTimeout":120, // 作业分割超时时间,默认120分钟 135 | "TaskResultCollectTimeout":120 // 任务结果合并超时时间,默认120分钟 136 | } 137 | ``` 138 | 139 | 运行时间计划格式说明: 140 | - HH:mm 每天定时运行 141 | - ddd HH:mm 每周定时运行 142 | - MM-dd HH:mm 每月定时运行 143 | - yyyy-MM-dd HH:mm 定时运行一次 144 | - dH 每d小时执行一次 145 | - dm 每m分钟执行一次 146 | 147 | 然后将这些全部打包到一个zip文件,文件名需要和job.json中的作业名称一致。 148 | 149 | #### 3、运行作业 150 | 151 | 将打包的zip文件通过Swift管理界面上传,稍等几秒钟,Swift会自动发现作业包,并分发到集群中。 152 | 现在你可以直接点击运行作业,也可以等待作业按照计划执行。 153 | 154 | ## 后记 155 | 156 | 这个程序还很简单,代码写的也有些丑陋,还有很多设想没有实现,如有兴趣,欢迎Fork! -------------------------------------------------------------------------------- /Swift.Core/CommonResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | namespace Swift.Core 3 | { 4 | /// 5 | /// 通用结果 6 | /// 7 | public class CommonResult 8 | { 9 | public CommonResult() 10 | { 11 | } 12 | 13 | public int ErrCode { get; set; } 14 | 15 | public string ErrMessage { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Swift.Core/CommunicationResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Swift.Core 8 | { 9 | /// 10 | /// 成员通信响应 11 | /// 12 | public class CommunicationResponse 13 | { 14 | public int ErrCode 15 | { 16 | get; 17 | set; 18 | } 19 | 20 | public string ErrMsg 21 | { 22 | get; 23 | set; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Swift.Core/Election/ConsulManagerElection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Threading; 4 | using Consul; 5 | using Swift.Core.Consul; 6 | using Swift.Core.Log; 7 | using LogLevel = Swift.Core.Log.LogLevel; 8 | 9 | namespace Swift.Core.Election 10 | { 11 | public class ConsulManagerElection : IManagerElection 12 | { 13 | private string _electionKey = string.Empty; 14 | private string _sessionId = string.Empty; 15 | private string _sessionCheckId = string.Empty; 16 | private string _currentMemberId = string.Empty; 17 | private readonly TimeSpan _defaultWatchInterval = new TimeSpan(0, 0, 60); 18 | private readonly TimeSpan _confirmWatchInterval = new TimeSpan(0, 0, 10); 19 | 20 | public ConsulManagerElection(string clusterName, string currentMemberId) 21 | { 22 | _electionKey = string.Format("Swift/{0}/Manager", clusterName); 23 | _currentMemberId = currentMemberId; 24 | _sessionCheckId = string.Format("CHECK:Swift-{0}-Member-{1}", clusterName, currentMemberId); 25 | } 26 | 27 | public ManagerElectionResult Elect(CancellationToken cancellationToken = default) 28 | { 29 | bool lockResult = false; 30 | string currentManagerId = string.Empty; 31 | bool isCurrentManagerOnline = false; 32 | 33 | // 创建一个关联到当前节点的Session 34 | if (!string.IsNullOrWhiteSpace(_sessionId)) 35 | { 36 | ConsulKV.RemoveSession(_sessionId); 37 | } 38 | _sessionId = ConsulKV.CreateSession(_sessionCheckId, 0); 39 | 40 | // 获取选举要锁定的Consul KV对象 41 | var kv = ConsulKV.Get(_electionKey, cancellationToken); 42 | if (kv == null) 43 | { 44 | kv = ConsulKV.Create(_electionKey); 45 | } 46 | 47 | if (string.IsNullOrWhiteSpace(kv.Session)) 48 | { 49 | LogWriter.Write("Elect->Session为空,开始尝试锁定", LogLevel.Debug); 50 | kv.Session = _sessionId; 51 | kv.Value = Encoding.UTF8.GetBytes(_currentMemberId); 52 | lockResult = ConsulKV.Acquire(kv, cancellationToken); 53 | LogWriter.Write($"锁定结果:{lockResult}", LogLevel.Debug); 54 | } 55 | 56 | // 无论参选成功与否,获取当前的Manager 57 | var managerKV = ConsulKV.Get(_electionKey, cancellationToken); 58 | if (managerKV != null) 59 | { 60 | currentManagerId = Encoding.UTF8.GetString(managerKV.Value); 61 | isCurrentManagerOnline = !string.IsNullOrWhiteSpace(managerKV.Session); 62 | } 63 | 64 | LogWriter.Write($"Elect->当前Manager:{currentManagerId}", LogLevel.Debug); 65 | 66 | return new ManagerElectionResult() 67 | { 68 | State = new ManagerElectionState() 69 | { 70 | Data = managerKV, 71 | CurrentManagerId = currentManagerId, 72 | IsManagerOnline = isCurrentManagerOnline, 73 | }, 74 | IsSuccess = lockResult, 75 | }; 76 | } 77 | 78 | public bool Reset(CancellationToken cancellationToken = default) 79 | { 80 | return ConsulKV.Delete(_electionKey, cancellationToken); 81 | } 82 | 83 | public void WatchState(ManagerElectionState state, Action processLatestState, CancellationToken cancellationToken = default) 84 | { 85 | KVPair consulKv = (KVPair)state.Data; 86 | ulong waitIndex = consulKv == null ? 0 : consulKv.ModifyIndex++; 87 | TimeSpan waitTime = state.IsManagerOnline ? _defaultWatchInterval : _confirmWatchInterval; 88 | var newConsulKv = ConsulKV.BlockGet(_electionKey, waitTime, waitIndex, cancellationToken); 89 | 90 | ManagerElectionState newState = null; 91 | if (newConsulKv != null) 92 | { 93 | newState = new ManagerElectionState 94 | { 95 | Data = newConsulKv, 96 | CurrentManagerId = Encoding.UTF8.GetString(newConsulKv.Value), 97 | IsManagerOnline = !string.IsNullOrWhiteSpace(newConsulKv.Session) 98 | }; 99 | } 100 | processLatestState?.Invoke(newState); 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Swift.Core/Election/IManagerElection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | 4 | namespace Swift.Core.Election 5 | { 6 | /// 7 | /// 管理员选举操作接口 8 | /// 9 | public interface IManagerElection 10 | { 11 | /// 12 | /// 执行选举操作 13 | /// 14 | /// 15 | ManagerElectionResult Elect(CancellationToken cancellationToken); 16 | 17 | /// 18 | /// 重新选举 19 | /// 20 | /// 21 | bool Reset(CancellationToken cancellationToken); 22 | 23 | /// 24 | /// 观察选举状态 25 | /// 26 | /// 当前状态 27 | /// 处理最新状态的方法 28 | /// 29 | void WatchState(ManagerElectionState state, Action processLatestState, CancellationToken cancellationToken); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Swift.Core/Election/ManagerElectCompletedEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | namespace Swift.Core.Election 3 | { 4 | public delegate void ManagerElectCompletedEvent(ManagerElectionResult result); 5 | } 6 | -------------------------------------------------------------------------------- /Swift.Core/Election/ManagerElectionFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | 4 | namespace Swift.Core.Election 5 | { 6 | public class ManagerElectionFactory 7 | { 8 | private readonly string _clusterName; 9 | private readonly string _currentMemberId; 10 | 11 | public ManagerElectionFactory(string clusterName, string currentMemberId) 12 | { 13 | _clusterName = clusterName; 14 | _currentMemberId = currentMemberId; 15 | } 16 | 17 | public IManagerElection Create(ManagerElectionOptions options) 18 | { 19 | if (options == null || string.IsNullOrWhiteSpace(options.ManagerElectionClass)) 20 | { 21 | return new ConsulManagerElection(_clusterName, _currentMemberId); 22 | } 23 | 24 | throw new NotImplementedException("未实现自定义Manager选举类创建"); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Swift.Core/Election/ManagerElectionOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | namespace Swift.Core.Election 3 | { 4 | /// 5 | /// Manager选举设置项 6 | /// 7 | public class ManagerElectionOptions 8 | { 9 | /// 10 | /// Mangger选举类,格式:含命名空间的完整类名,所在程序集 11 | /// 12 | public string ManagerElectionClass { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Swift.Core/Election/ManagerElectionResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | namespace Swift.Core.Election 3 | { 4 | public class ManagerElectionResult 5 | { 6 | /// 7 | /// 当前节点是否选举成功 8 | /// 9 | public bool IsSuccess { get; set; } 10 | 11 | /// 12 | /// 选举状态 13 | /// 14 | public ManagerElectionState State { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Swift.Core/Election/ManagerElectionState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | namespace Swift.Core.Election 3 | { 4 | /// 5 | /// Manager选举状态 6 | /// 7 | public class ManagerElectionState 8 | { 9 | /// 10 | /// 选举状态数据 11 | /// 12 | public object Data { get; set; } 13 | 14 | /// 15 | /// Manager是否在线 16 | /// 17 | public bool IsManagerOnline { get; set; } 18 | 19 | /// 20 | /// 当前ManagerId 21 | /// 22 | public string CurrentManagerId { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Swift.Core/EnumExecutableFileType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | namespace Swift.Core 3 | { 4 | /// 5 | /// 可执行文件类型 6 | /// 7 | [Flags] 8 | public enum EnumExecutableFileType 9 | { 10 | /// 11 | /// 直接可执行文件 12 | /// 13 | DirectExe = 1, 14 | 15 | /// 16 | /// dotnet core 17 | /// 18 | DotNet = 2, 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Swift.Core/EnumJobStatus.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Swift.Core 8 | { 9 | /// 10 | /// 作业记录状态 11 | /// 12 | public enum EnumJobRecordStatus 13 | { 14 | /// 15 | /// 待处理 16 | /// 17 | Pending = 0, 18 | 19 | /// 20 | /// 正在制定计划 21 | /// 22 | PlanMaking = 1, 23 | 24 | /// 25 | /// 已制定计划 26 | /// 27 | PlanMaked = 2, 28 | 29 | /// 30 | /// 任务正在执行 31 | /// 32 | TaskExecuting = 3, 33 | 34 | /// 35 | /// 任务处理完毕 36 | /// 37 | TaskCompleted = 4, 38 | 39 | /// 40 | /// 任务同步完毕 41 | /// 42 | TaskSynced = 5, 43 | 44 | /// 45 | /// 任务合并中 46 | /// 47 | TaskMerging = 6, 48 | 49 | /// 50 | /// 任务合并完毕,作业成功结束 51 | /// 52 | TaskMerged = 7, 53 | 54 | /// 55 | /// 正在取消 56 | /// 57 | Canceling = 8, 58 | 59 | /// 60 | /// 已取消 61 | /// 62 | Canceled = 9, 63 | 64 | /// 65 | /// 制定计划失败 66 | /// 67 | PlanFailed = -1, 68 | 69 | /// 70 | /// 任务执行失败 71 | /// 72 | TaskExecutingFailed = -2, 73 | 74 | /// 75 | /// 任务合并失败 76 | /// 77 | TaskMergeFailed = -3, 78 | 79 | /// 80 | /// 取消失败 81 | /// 82 | CancelFailed = -4, 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Swift.Core/EnumMemberRole.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Swift.Core 8 | { 9 | /// 10 | /// 集群成员角色枚举 11 | /// 12 | public enum EnumMemberRole 13 | { 14 | /// 15 | /// 经理 16 | /// 17 | Manager = 0, 18 | 19 | /// 20 | /// 普通工人 21 | /// 22 | Worker = 1 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Swift.Core/EnumTaskStatus.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Swift.Core 8 | { 9 | /// 10 | /// 任务状态 11 | /// 12 | public enum EnumTaskStatus 13 | { 14 | /// 15 | /// 未处理 16 | /// 17 | Pending = 0, 18 | /// 19 | /// 处理中 20 | /// 21 | Executing = 1, 22 | /// 23 | /// 处理完成 24 | /// 25 | Completed = 2, 26 | /// 27 | /// 已同步任务结果 28 | /// 29 | Synced = 3, 30 | /// 31 | /// 正在取消 32 | /// 33 | Canceling = 4, 34 | /// 35 | /// 已取消 36 | /// 37 | Canceled = 5, 38 | /// 39 | /// 失败 40 | /// 41 | Failed = -1, 42 | /// 43 | /// 取消失败 44 | /// 45 | CancelFailed = -2, 46 | /// 47 | /// 同步任务结果失败 48 | /// 49 | SyncFailed = -3, 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Swift.Core/ExtensionException/JobPackageConfigExtractException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Swift.Core.ExtensionException 8 | { 9 | public class JobPackageConfigExtractException : System.Exception 10 | { 11 | public JobPackageConfigExtractException(string message) 12 | : base(message) 13 | { 14 | } 15 | 16 | public JobPackageConfigExtractException(string message, System.Exception ex) 17 | : base(message, ex) 18 | { 19 | } 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /Swift.Core/ExtensionException/MemberNotFoundException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Swift.Core.ExtensionException 8 | { 9 | /// 10 | /// 成员不存在异常 11 | /// 12 | public class MemberNotFoundException : System.Exception 13 | { 14 | public MemberNotFoundException(string message) 15 | : base(message) 16 | { 17 | } 18 | 19 | public MemberNotFoundException(string message, System.Exception ex) 20 | : base(message, ex) 21 | { 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Swift.Core/HttpServer.cs: -------------------------------------------------------------------------------- 1 | using Swift.Core.Log; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Net; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Swift.Core 10 | { 11 | public class HttpServer 12 | { 13 | private HttpListener listener = null; 14 | private int serverPort = 9631; 15 | private string serverIp = string.Empty; 16 | 17 | public HttpServer(string ip, int port) 18 | { 19 | serverIp = ip; 20 | serverPort = port; 21 | } 22 | 23 | /// 24 | /// 获取基础Url 25 | /// 26 | public string BaseUrl 27 | { 28 | get 29 | { 30 | return string.Format("http://{0}:{1}/", serverIp, serverPort); 31 | } 32 | } 33 | 34 | /// 35 | /// 启动HttpServer 36 | /// 37 | public void Start() 38 | { 39 | listener = new HttpListener(); 40 | listener.Prefixes.Add(BaseUrl); 41 | listener.Start(); 42 | LogWriter.Write(string.Format("HttpServer已经启动:http://{0}:{1}", serverIp, serverPort)); 43 | 44 | listener.BeginGetContext(new AsyncCallback(GetContextCallBack), listener); 45 | } 46 | 47 | /// 48 | /// 关闭HttpServer 49 | /// 50 | public void Stop() 51 | { 52 | listener.Close(); 53 | } 54 | 55 | /// 56 | /// 处理具体的请求 57 | /// 58 | /// 59 | protected virtual void ProcessRequest(HttpListenerContext context) 60 | { 61 | } 62 | 63 | /// 64 | /// 获取上下文回调 65 | /// 66 | /// 67 | private void GetContextCallBack(IAsyncResult ar) 68 | { 69 | try 70 | { 71 | listener = ar.AsyncState as HttpListener; 72 | HttpListenerContext context = listener.EndGetContext(ar); 73 | listener.BeginGetContext(new AsyncCallback(GetContextCallBack), listener); 74 | 75 | ProcessRequest(context); 76 | } 77 | catch (Exception ex) 78 | { 79 | LogWriter.Write("异步处理Http请求异常", ex); 80 | } 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Swift.Core/IConfigCenter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | 4 | namespace Swift.Core 5 | { 6 | public interface IConfigCenter 7 | { 8 | /// 9 | /// 尝试更新作业实例状态 10 | /// 11 | /// The job status. 12 | /// Job. 13 | /// Status. 14 | /// 错误代码:0无错误 1不能设置为这个状态 2无需重复设置状态 3作业不存在 15 | /// 更新后最新的作业信息 16 | /// Cancellation token. 17 | bool TryUpdateJobStatus(JobBase job, EnumJobRecordStatus status, out int errCode, out JobBase latestJob, CancellationToken cancellationToken); 18 | 19 | /// 20 | /// 尝试更新任务状态 21 | /// 22 | /// true, if update task status was tryed, false otherwise. 23 | /// Task. 24 | /// Status. 25 | /// 错误代码:0无错误 1不能设置为这个状态 2无需重复设置状态 3作业或任务不存在 26 | /// Latest job. 27 | /// Cancellation token. 28 | bool TryUpdateTaskStatus(JobTask task, EnumTaskStatus status, out int errCode, out JobBase latestJob, CancellationToken cancellationToken); 29 | 30 | /// 31 | /// 更新作业任务计划 32 | /// 33 | /// The job task plan. 34 | /// Job. 35 | /// Cancellation token. 36 | JobBase UpdateJobTaskPlan(JobBase job, CancellationToken cancellationToken); 37 | 38 | /// 39 | /// 更新最后一次作业记录 40 | /// 41 | /// Job base. 42 | /// Cancellation token. 43 | bool UpdateLastJobRecord(JobBase newJob, CancellationToken cancellationToken); 44 | 45 | /// 46 | /// 获取作业记录 47 | /// 48 | /// The job record. 49 | /// Job config. 50 | /// Cluster. 51 | /// Cancellation token. 52 | JobBase GetJobRecord(JobConfig jobConfig, Cluster cluster, CancellationToken cancellationToken); 53 | 54 | /// 55 | /// 获取作业记录 56 | /// 57 | /// The job record. 58 | /// Job name. 59 | /// Job identifier. 60 | /// Cluster. 61 | /// Cancellation token. 62 | JobBase GetJobRecord(string jobName, string jobId, Cluster cluster, CancellationToken cancellationToken); 63 | 64 | /// 65 | /// 取消作业记录 66 | /// 67 | /// The job record. 68 | bool CancelJobRecord(JobBase job); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Swift.Core/JobWrapper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Swift.Core 8 | { 9 | /// 10 | /// 作业包装类:用于在执行各种作业时作业类型多变而导致表达困难的问题,可方便转换为JobBase具体子类的实例 11 | /// 12 | public class JobWrapper : JobBase 13 | { 14 | public JobWrapper() 15 | { 16 | } 17 | 18 | public JobWrapper(JobBase job) 19 | { 20 | if (job != null) 21 | { 22 | Id = job.Id; 23 | Name = job.Name; 24 | FileName = job.FileName; 25 | JobClassName = job.JobClassName; 26 | Status = job.Status; 27 | Version = job.Version; 28 | TaskPlan = job.TaskPlan; 29 | ModifyIndex = job.ModifyIndex; 30 | TaskExecuteTimeout = job.TaskExecuteTimeout; 31 | JobSplitTimeout = job.JobSplitTimeout; 32 | TaskResultCollectTimeout = job.TaskResultCollectTimeout; 33 | MemberUnavailableThreshold = job.MemberUnavailableThreshold; 34 | } 35 | } 36 | 37 | /// 38 | /// 分割作业为不同的任务 39 | /// 40 | /// 41 | public override JobTask[] Split() 42 | { 43 | throw new NotImplementedException("这个方法不会被实现,应继承JobBase实现自己的Split"); 44 | } 45 | 46 | /// 47 | /// 处理具体的任务 48 | /// 49 | /// 50 | /// 51 | public override string ExecuteTask(JobTask task) 52 | { 53 | throw new NotImplementedException("这个方法不会被实现,应继承JobBase实现自己的Process"); 54 | } 55 | 56 | /// 57 | /// 汇集各个任务的处理结果 58 | /// 59 | /// 60 | public override string Collect(IEnumerable tasks) 61 | { 62 | throw new NotImplementedException("这个方法不会被实现,应继承JobBase实现自己的Collect"); 63 | } 64 | 65 | /// 66 | /// 转换为JobBase的某个具体子类的实例 67 | /// 68 | /// 69 | /// 70 | public T ConvertTo() where T : JobBase 71 | { 72 | var t = System.Activator.CreateInstance(); 73 | t.FileName = this.FileName; 74 | t.Id = this.Id; 75 | t.Name = this.Name; 76 | t.JobClassName = this.JobClassName; 77 | t.Status = this.Status; 78 | t.TaskPlan = this.TaskPlan; 79 | t.CreateTime = this.CreateTime; 80 | t.ModifyIndex = this.ModifyIndex; 81 | t.Version = this.Version; 82 | t.TaskExecuteTimeout = this.TaskExecuteTimeout; 83 | t.JobSplitTimeout = this.JobSplitTimeout; 84 | t.TaskResultCollectTimeout = this.TaskResultCollectTimeout; 85 | t.MemberUnavailableThreshold = this.MemberUnavailableThreshold; 86 | return t; 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Swift.Core/Log/LogLevel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Swift.Core.Log 8 | { 9 | /// 10 | /// 日志级别 11 | /// 12 | internal enum LogLevel 13 | { 14 | Trace = 0, 15 | Debug, 16 | Info, 17 | Warn, 18 | Error 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Swift.Core/Log/LogWriter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Swift.Core.Log 8 | { 9 | /// 10 | /// 日志记录类 11 | /// 12 | internal class LogWriter 13 | { 14 | private static NLog.ILogger logger; 15 | 16 | static LogWriter() 17 | { 18 | logger = NLog.LogManager.GetLogger("SwiftLogger"); 19 | } 20 | 21 | public static void Write(string message) 22 | { 23 | Write(message, LogLevel.Info); 24 | } 25 | 26 | public static void Write(string message, LogLevel level) 27 | { 28 | Console.WriteLine(string.Format("{0} [{1}] {2}", DateTime.Now.ToString(), level.ToString(), message)); 29 | 30 | switch (level) 31 | { 32 | case LogLevel.Trace: 33 | logger.Trace(message); 34 | break; 35 | case LogLevel.Debug: 36 | logger.Debug(message); 37 | break; 38 | case LogLevel.Info: 39 | logger.Info(message); 40 | break; 41 | case LogLevel.Warn: 42 | logger.Warn(message); 43 | break; 44 | case LogLevel.Error: 45 | logger.Error(message); 46 | break; 47 | } 48 | } 49 | 50 | public static void Write(string message, Exception ex) 51 | { 52 | Write(message, ex, LogLevel.Error); 53 | } 54 | 55 | public static void Write(string message, Exception ex, LogLevel level) 56 | { 57 | Console.WriteLine(string.Format("{0} [{1}] {2}", DateTime.Now.ToString(), level.ToString(), message)); 58 | if (ex != null) 59 | { 60 | Console.WriteLine(string.Format("{0} [{1}] {2}", DateTime.Now.ToString(), level.ToString(), ex.Message)); 61 | Console.WriteLine(string.Format("{0} [{1}] {2}", DateTime.Now.ToString(), level.ToString(), ex.StackTrace)); 62 | } 63 | 64 | switch (level) 65 | { 66 | case LogLevel.Trace: 67 | logger.Trace(ex, message); 68 | break; 69 | case LogLevel.Debug: 70 | logger.Debug(ex, message); 71 | break; 72 | case LogLevel.Info: 73 | logger.Info(ex, message); 74 | break; 75 | case LogLevel.Warn: 76 | logger.Warn(ex, message); 77 | break; 78 | case LogLevel.Error: 79 | logger.Error(ex, message); 80 | break; 81 | } 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Swift.Core/MemberWrapper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Swift.Core 8 | { 9 | /// 10 | /// 成员包装类:用于在反序列化时 11 | /// 12 | public class MemberWrapper : Member 13 | { 14 | public MemberWrapper() 15 | { 16 | } 17 | 18 | public MemberWrapper(Member member) 19 | { 20 | if (member != null) 21 | { 22 | Id = this.Id; 23 | FirstRegisterTime = this.FirstRegisterTime; 24 | OfflineTime = this.OfflineTime; 25 | OnlineTime = this.OnlineTime; 26 | Status = this.Status; 27 | } 28 | } 29 | 30 | /// 31 | /// 转换为Member的某个具体子类的实例 32 | /// 33 | /// 34 | /// 35 | public T ConvertTo() where T : Member 36 | { 37 | var t = System.Activator.CreateInstance(); 38 | t.Id = this.Id; 39 | t.FirstRegisterTime = this.FirstRegisterTime; 40 | t.OfflineTime = this.OfflineTime; 41 | t.OnlineTime = this.OnlineTime; 42 | t.Status = this.Status; 43 | return t; 44 | } 45 | 46 | /// 47 | /// 转换为基类 48 | /// 49 | /// 50 | public Member ConvertToBase() 51 | { 52 | return this; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Swift.Core/OS/IOSAPI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace Swift.Core.OS 5 | { 6 | /// 7 | /// 操作系统API接口 8 | /// 9 | public interface IOSAPI 10 | { 11 | /// 12 | /// 获取进程启动时的命令行 13 | /// 14 | /// The process commmand line. 15 | /// Process. 16 | string GetProcessCommmandLine(Process process); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Swift.Core/OS/Linux/LinuxAPI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace Swift.Core.OS.Linux 5 | { 6 | public class LinuxAPI : IOSAPI 7 | { 8 | public string GetProcessCommmandLine(Process process) 9 | { 10 | // https://stackoverflow.com/questions/821837/how-to-get-the-command-line-args-passed-to-a-running-process-on-unix-linux-syste 11 | 12 | return Bash("xargs -0 < /proc/" + process.Id + "/cmdline"); 13 | } 14 | 15 | /// 16 | /// 执行命令 17 | /// 18 | /// The bash. 19 | /// Cmd. 20 | private string Bash(string cmd) 21 | { 22 | var escapedArgs = cmd.Replace("\"", "\\\""); 23 | 24 | var process = new Process() 25 | { 26 | StartInfo = new ProcessStartInfo 27 | { 28 | FileName = "/bin/bash", 29 | Arguments = $"-c \"{escapedArgs}\"", 30 | RedirectStandardOutput = true, 31 | UseShellExecute = false, 32 | CreateNoWindow = true, 33 | } 34 | }; 35 | process.Start(); 36 | string result = process.StandardOutput.ReadToEnd(); 37 | process.WaitForExit(); 38 | return result.TrimEnd(Environment.NewLine.ToCharArray()).Trim(); 39 | } 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Swift.Core/OS/OSAPIFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Runtime.InteropServices; 4 | using Swift.Core.OS.Linux; 5 | using Swift.Core.OS.OSX; 6 | using Swift.Core.OS.Windows; 7 | 8 | namespace Swift.Core.OS 9 | { 10 | internal static class OSAPIFactory 11 | { 12 | public static IOSAPI Create() 13 | { 14 | var os = GetOSPlatform(); 15 | if (os == OSPlatform.Windows) 16 | { 17 | return new WindowsAPI(); 18 | } 19 | else if (os == OSPlatform.Linux) 20 | { 21 | return new LinuxAPI(); 22 | } 23 | else if (os == OSPlatform.OSX) 24 | { 25 | return new OSXAPI(); 26 | } 27 | 28 | throw new PlatformNotSupportedException("不支持此操作系统"); 29 | } 30 | 31 | /// 32 | /// Get OS platform 33 | /// https://code.msdn.microsoft.com/How-to-determine-operating-c90d351b#content 34 | /// 35 | /// 36 | public static OSPlatform GetOSPlatform() 37 | { 38 | OSPlatform osPlatform = OSPlatform.Create("Other Platform"); 39 | // Check if it's windows 40 | bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); 41 | osPlatform = isWindows ? OSPlatform.Windows : osPlatform; 42 | // Check if it's osx 43 | bool isOSX = RuntimeInformation.IsOSPlatform(OSPlatform.OSX); 44 | osPlatform = isOSX ? OSPlatform.OSX : osPlatform; 45 | // Check if it's Linux 46 | bool isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); 47 | osPlatform = isLinux ? OSPlatform.Linux : osPlatform; 48 | return osPlatform; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Swift.Core/OS/OSX/OSXAPI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace Swift.Core.OS.OSX 5 | { 6 | public class OSXAPI : IOSAPI 7 | { 8 | public OSXAPI() 9 | { 10 | } 11 | 12 | public string GetProcessCommmandLine(Process process) 13 | { 14 | // https://superuser.com/questions/27748/how-to-get-command-line-of-unix-process 15 | 16 | return Bash("ps -p " + process.Id + " -o command="); 17 | } 18 | 19 | /// 20 | /// 执行命令 21 | /// 22 | /// The bash. 23 | /// Cmd. 24 | private string Bash(string cmd) 25 | { 26 | var escapedArgs = cmd.Replace("\"", "\\\""); 27 | 28 | var process = new Process() 29 | { 30 | StartInfo = new ProcessStartInfo 31 | { 32 | FileName = "/bin/bash", 33 | Arguments = $"-c \"{escapedArgs}\"", 34 | RedirectStandardOutput = true, 35 | UseShellExecute = false, 36 | CreateNoWindow = true, 37 | } 38 | }; 39 | process.Start(); 40 | string result = process.StandardOutput.ReadToEnd(); 41 | process.WaitForExit(); 42 | return result.TrimEnd(Environment.NewLine.ToCharArray()).Trim(); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Swift.Core/OS/Windows/WindowsAPI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Management; 4 | 5 | namespace Swift.Core.OS.Windows 6 | { 7 | public class WindowsAPI : IOSAPI 8 | { 9 | public string GetProcessCommmandLine(Process process) 10 | { 11 | using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT CommandLine FROM Win32_Process WHERE ProcessId = " + process.Id)) 12 | using (ManagementObjectCollection objects = searcher.Get()) 13 | { 14 | String commandLine = ""; 15 | foreach (ManagementObject commandLineObject in objects) 16 | { 17 | commandLine += (String)commandLineObject["CommandLine"]; 18 | } 19 | 20 | return commandLine.TrimEnd(Environment.NewLine.ToCharArray()).Trim(); 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Swift.Core/ResourceManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | namespace Swift.Core 3 | { 4 | /// 5 | /// 集群资源管理 6 | /// 7 | public class ResourceManager 8 | { 9 | // 每个节点上传自己的总可执行任务数到配置中心 10 | // Manager从配置中心获取每个节点的总可执行任务数和排队的任务数,从节点获取其正在执行的任务数 11 | // Manager分配任务时根据这个空闲任务数进行分配 12 | 13 | /// 14 | /// 获取当前节点可执行任务数限制 15 | /// 16 | /// The current execute amount limit. 17 | public static int GetCurrentExecuteAmountLimit() 18 | { 19 | return Environment.ProcessorCount; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Swift.Core/Swift.Core.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | 0.1.0 6 | bosima 7 | Swift核心程序。 8 | 0.1.0 9 | 0.1.0 10 | bosima 11 | 12 | 13 | 7.1 14 | 15 | 16 | 7.1 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Swift.Core/SwiftProcessEventActions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace Swift.Core 5 | { 6 | /// 7 | /// Swift进程事件 8 | /// 9 | public class SwiftProcessEventActions 10 | { 11 | public Action OutputAction { get; set; } 12 | public Action ErrorAction { get; set; } 13 | public Action StartedAction { get; set; } 14 | public Action ExitAction { get; set; } 15 | public Action TimeoutAction { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Swift.Core/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Swift.DemoJob/DemoJob.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Swift.Core; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | 10 | namespace Swift.DemoJob 11 | { 12 | public class DemoJob : JobBase 13 | { 14 | /// 15 | /// 将工作分成若干任务 16 | /// 17 | public override JobTask[] Split() 18 | { 19 | string input = "With more than 35,000 production deployments of RabbitMQ world-wide at small startups and large enterprises, RabbitMQ is the most popular open source message broker."; 20 | 21 | int taskNum = 4; 22 | int perTaskCharNos = (int)Math.Ceiling(input.Length / (double)taskNum); 23 | 24 | List taskList = new List(); 25 | int k = 1; 26 | for (int i = 0; i < taskNum; i++) 27 | { 28 | if (i * perTaskCharNos < input.Length - 1) 29 | { 30 | var subLength = perTaskCharNos; 31 | if (i * perTaskCharNos + subLength > input.Length) 32 | { 33 | subLength = input.Length - i * perTaskCharNos; 34 | } 35 | 36 | // 需求只需要时字符串,格式自己定义 37 | string requirement = input.Substring(i * perTaskCharNos, subLength); 38 | var task = new JobTask() 39 | { 40 | Id = k, 41 | Job = new JobWrapper(this), 42 | Requirement = requirement, 43 | }; 44 | taskList.Add(task); 45 | k++; 46 | } 47 | } 48 | 49 | return taskList.ToArray(); 50 | } 51 | 52 | /// 53 | /// 执行任务 54 | /// 55 | /// 56 | public override string ExecuteTask(JobTask task) 57 | { 58 | Dictionary stat = new Dictionary(); 59 | 60 | // 使用自己定义的需求 61 | var requirement = task.Requirement; 62 | if (requirement != null) 63 | { 64 | foreach (var c in requirement) 65 | { 66 | if (stat.ContainsKey(c)) 67 | { 68 | stat[c]++; 69 | } 70 | else 71 | { 72 | stat.Add(c, 1); 73 | } 74 | } 75 | } 76 | 77 | // 测试超时的处理 78 | Thread.Sleep(1 * 60 * 1000); 79 | 80 | // 如果任务结果文件比较大,比如300M,会导致网速和内存占用较大,请考虑写到别的地方去,这里返回个实际结果的地址就行了 81 | // 返回字符串的格式自定义即可 82 | return JsonConvert.SerializeObject(stat); 83 | } 84 | 85 | /// 86 | /// 汇集各个任务的处理结果 87 | /// 88 | /// 89 | public override string Collect(IEnumerable tasks) 90 | { 91 | Dictionary stat = new Dictionary(); 92 | 93 | foreach (var task in tasks) 94 | { 95 | // 自定义的任务结果字符串 96 | var taskResult = task.Result; 97 | if (!string.IsNullOrWhiteSpace(taskResult)) 98 | { 99 | var taskStat = JsonConvert.DeserializeObject>(taskResult); 100 | 101 | foreach (var c in taskStat.Keys) 102 | { 103 | if (stat.ContainsKey(c)) 104 | { 105 | stat[c] += taskStat[c]; 106 | } 107 | else 108 | { 109 | stat[c] = taskStat[c]; 110 | } 111 | } 112 | } 113 | } 114 | 115 | // 如果结果太大,比如超过1G,写文件可能会很慢,请考虑写到别的地方去,这里返回个实际结果的地址就行了 116 | // 返回字符串的格式自定义即可 117 | return JsonConvert.SerializeObject(stat); 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /Swift.DemoJob/Swift.DemoJob.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Library 5 | netcoreapp3.1 6 | bosima 7 | Swift演示程序。 8 | 0.1.0 9 | 0.1.0 10 | bosima 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Swift.DemoJob/job.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "DemoJob", 3 | "FileName": "Swift.JobEntryPoint.dll", 4 | "ExeType": "dotnet", 5 | "JobClassName": "Swift.DemoJob.dll,Swift.DemoJob.DemoJob", 6 | "RunTimePlan": [ "10m" ], 7 | "TaskExecuteTimeout": 9, 8 | "MemberUnavailableThreshold": 5 9 | } -------------------------------------------------------------------------------- /Swift.DemoJob/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /Swift.JobEntryPoint/NLog.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 12 | 13 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Swift.JobEntryPoint/Swift.JobEntryPoint.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | Always 17 | 18 | 19 | 20 | 21 | PreserveNewest 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Swift.JobEntryPoint/Swift.JobEntryPoint.runtimeconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "runtimeOptions": { 3 | "tfm": "netcoreapp3.1", 4 | "framework": { 5 | "name": "Microsoft.NETCore.App", 6 | "version": "3.1.0" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Swift.Management/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Consul; 8 | using Microsoft.AspNetCore.Mvc; 9 | using Newtonsoft.Json; 10 | using Swift.Core; 11 | using Swift.Core.Consul; 12 | using Swift.Management.Models; 13 | using Swift.Management.Swift; 14 | 15 | namespace Swift.Management.Controllers 16 | { 17 | public class HomeController : Controller 18 | { 19 | private readonly ISwiftService _swift; 20 | 21 | public HomeController(ISwiftService swift) 22 | { 23 | _swift = swift; 24 | } 25 | 26 | public IActionResult Index() 27 | { 28 | var cluster = _swift.GetClusters(); 29 | return View(cluster); 30 | } 31 | 32 | public IActionResult Members(string cluster) 33 | { 34 | ViewBag.Manager = _swift.GetManager(cluster); 35 | ViewBag.ClusterName = cluster; 36 | var members = _swift.GetMembers(cluster); 37 | return View(members); 38 | } 39 | 40 | public IActionResult Jobs(string cluster) 41 | { 42 | ViewBag.ClusterName = cluster; 43 | var jobConfigs = _swift.GetJobConfigs(cluster); 44 | return View(jobConfigs); 45 | } 46 | 47 | public IActionResult JobRecords(string cluster, string job, DateTime? date) 48 | { 49 | ViewBag.ClusterName = cluster; 50 | ViewBag.JobName = job; 51 | var jobRecordss = _swift.GetJobRecords(cluster, job, date); 52 | 53 | if (date.HasValue) 54 | { 55 | ViewBag.SpecifiedDate = date.Value.ToString("yyyy-MM-dd"); 56 | } 57 | else 58 | { 59 | if (jobRecordss.Count > 0) 60 | { 61 | ViewBag.SpecifiedDate = jobRecordss[0].CreateTime.ToString("yyyy-MM-dd"); 62 | } 63 | } 64 | 65 | return View(jobRecordss); 66 | } 67 | 68 | public IActionResult RestartManagerElection(string cluster) 69 | { 70 | try 71 | { 72 | _swift.RestartManagerElection(cluster); 73 | } 74 | catch (Exception ex) 75 | { 76 | return new ObjectResult(new { errCode = 1, errMessage = ex.Message }); 77 | } 78 | 79 | return new ObjectResult(new { errCode = 0 }); 80 | } 81 | 82 | public IActionResult About() 83 | { 84 | ViewBag.Message = "Swift是一个分布式作业处理框架,支持将任务分发到多台服务器并行处理,可成倍提升大量数据的处理速度。"; 85 | 86 | return View(); 87 | } 88 | 89 | public IActionResult Contact() 90 | { 91 | ViewBag.Message = "https://github.com/bosima/Swift"; 92 | 93 | return View(); 94 | } 95 | 96 | [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] 97 | public IActionResult Error() 98 | { 99 | return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /Swift.Management/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base 2 | WORKDIR /app 3 | EXPOSE 80 4 | 5 | FROM microsoft/dotnet:2.1-sdk AS build 6 | WORKDIR /src 7 | COPY Swift.Management/Swift.Management.csproj Swift.Management/ 8 | COPY Swift.Core/Swift.Core.csproj Swift.Core/ 9 | RUN dotnet restore Swift.Management/Swift.Management.csproj 10 | COPY . . 11 | WORKDIR /src/Swift.Management 12 | RUN dotnet build Swift.Management.csproj -c Release -o /app 13 | 14 | FROM build AS publish 15 | RUN dotnet publish Swift.Management.csproj -c Release -o /app 16 | 17 | FROM base AS final 18 | WORKDIR /app 19 | COPY --from=publish /app . 20 | ENTRYPOINT ["dotnet", "Swift.Management.dll"] 21 | -------------------------------------------------------------------------------- /Swift.Management/Models/ErrorViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Swift.Management.Models 4 | { 5 | public class ErrorViewModel 6 | { 7 | public string RequestId { get; set; } 8 | 9 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 10 | } 11 | } -------------------------------------------------------------------------------- /Swift.Management/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.Logging; 10 | 11 | namespace Swift.Management 12 | { 13 | public class Program 14 | { 15 | public static void Main(string[] args) 16 | { 17 | CreateWebHostBuilder(args).Build().Run(); 18 | } 19 | 20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 21 | WebHost.CreateDefaultBuilder(args) 22 | .UseStartup(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Swift.Management/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Builder; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Microsoft.AspNetCore.Http; 8 | using Microsoft.AspNetCore.HttpsPolicy; 9 | using Microsoft.AspNetCore.Mvc; 10 | using Microsoft.Extensions.Configuration; 11 | using Microsoft.Extensions.DependencyInjection; 12 | using Microsoft.Extensions.Hosting; 13 | using Swift.Management.Swift; 14 | 15 | namespace Swift.Management 16 | { 17 | public class Startup 18 | { 19 | public Startup(IConfiguration configuration) 20 | { 21 | Configuration = configuration; 22 | } 23 | 24 | public IConfiguration Configuration { get; } 25 | 26 | // This method gets called by the runtime. Use this method to add services to the container. 27 | public void ConfigureServices(IServiceCollection services) 28 | { 29 | services.AddSingleton(); 30 | 31 | services.AddControllersWithViews(); 32 | } 33 | 34 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 35 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 36 | { 37 | if (env.IsDevelopment()) 38 | { 39 | app.UseDeveloperExceptionPage(); 40 | } 41 | else 42 | { 43 | app.UseExceptionHandler("/Home/Error"); 44 | } 45 | 46 | app.UseStaticFiles(); 47 | 48 | app.UseRouting(); 49 | 50 | app.UseEndpoints(endpoints => 51 | { 52 | endpoints.MapControllerRoute( 53 | name: "default", 54 | pattern: "{controller=Home}/{action=Index}/{id?}"); 55 | }); 56 | 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Swift.Management/Swift.Management.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /Swift.Management/Swift/ISwiftService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Microsoft.AspNetCore.Http; 3 | using Swift.Core; 4 | 5 | namespace Swift.Management.Swift 6 | { 7 | public interface ISwiftService 8 | { 9 | List GetClusters(); 10 | 11 | JobConfig GetJobConfig(string clusterName, string jobName); 12 | 13 | bool Run(string clusterName, string jobName); 14 | 15 | bool Cancel(string clusterName, string jobName, string jobId); 16 | 17 | Member GetManager(string clusterName); 18 | 19 | void RestartManagerElection(string clusterName); 20 | 21 | List GetMembers(string clusterName); 22 | 23 | List GetJobRecords(string clusterName, string jobName, System.DateTime? date); 24 | 25 | List GetJobConfigs(string clusterName); 26 | 27 | bool PublishJobPackage(string clusterName, FormFile file); 28 | 29 | byte[] DownloadJobResult(string clusterName, string jobName, string jobId); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Swift.Management/Views/Home/About.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "About"; 3 | } 4 |

@ViewBag.Title.

5 |

@ViewBag.Message

-------------------------------------------------------------------------------- /Swift.Management/Views/Home/Contact.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Contact"; 3 | } 4 |

@ViewBag.Title.

5 |

@ViewBag.Message

-------------------------------------------------------------------------------- /Swift.Management/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | @{ 3 | ViewBag.Title = "管理中心"; 4 | } 5 | 6 |
7 |

Swift是一个分布式批处理框架,通过将作业分割并分发到多台机器并行处理,成倍提升了数据的处理速度。

8 |
9 | 10 |
11 |
12 |

当前集群

13 | 14 | 15 | 16 | 17 | 18 | 19 | @foreach (var item in Model) 20 | { 21 | 22 | 23 | 24 | 25 | 26 | } 27 |
集群名称成员作业
@Html.DisplayFor(modelItem => item.Name)@Html.ActionLink("查看", "Members", new { cluster = item.Name })@Html.ActionLink("查看", "Jobs", new { cluster = item.Name })
28 |
29 |
-------------------------------------------------------------------------------- /Swift.Management/Views/Home/Members.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | 3 | @{ 4 | ViewBag.Title = "成员"; 5 | } 6 | 7 | @section scripts{ 8 | 43 | } 44 | 45 |

集群 @ViewBag.ClusterName 成员

46 | 47 |

48 | 返回 49 | 刷新 50 |

51 |

52 | 53 |

54 | 55 | 56 | 59 | 62 | 65 | 68 | 69 | 70 | @foreach (var item in Model) 71 | { 72 | 73 | 83 | 86 | 89 | 92 | 93 | } 94 |
57 | Id 58 | 60 | 状态 61 | 63 | 最近上线时间 64 | 66 | 最近离线时间 67 |
74 | @Html.DisplayFor(modelItem => item.Id) 75 | 76 | @{ 77 | if (ViewBag.Manager != null && ViewBag.Manager.Id == item.Id) 78 | { 79 | (Manager) 80 | } 81 | } 82 | 84 | @(item.Status == 0 ? "离线" : "在线") 85 | 87 | @(item.OnlineTime.HasValue ? item.OnlineTime.Value.ToString("yyyy-MM-dd HH:mm:ss") : string.Empty) 88 | 90 | @(item.OfflineTime.HasValue ? item.OfflineTime.Value.ToString("yyyy-MM-dd HH:mm:ss") : string.Empty) 91 |
95 | 96 | -------------------------------------------------------------------------------- /Swift.Management/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 错误 7 | 8 | 9 |
10 |

错误。

11 |

处理你的请求时出错。

12 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /Swift.Management/Views/Shared/_CookieConsentPartial.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Http.Features 2 | 3 | @{ 4 | var consentFeature = Context.Features.Get 5 | (); 6 | var showBanner = !consentFeature?.CanTrack ?? false; 7 | var cookieString = consentFeature?.CreateConsentCookie(); 8 | } 9 | 10 | @if (showBanner) 11 | { 12 | 34 | 42 | } 43 | -------------------------------------------------------------------------------- /Swift.Management/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | @ViewBag.Title - Swift 8 | 9 | 10 | @RenderSection("header", required: false) 11 | 12 | 13 | 29 |
30 | @RenderBody() 31 |
32 |
33 |

© @DateTime.Now.Year - Swift

34 |
35 |
36 | 37 | 38 | @RenderSection("scripts", required: false) 39 | 40 | 41 | -------------------------------------------------------------------------------- /Swift.Management/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using Swift.Management 2 | @using Swift.Management.Models 3 | @using Swift.Core 4 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 5 | -------------------------------------------------------------------------------- /Swift.Management/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /Swift.Management/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Swift.Management/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Warning" 5 | } 6 | }, 7 | "AllowedHosts": "*" 8 | } 9 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | /* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification\ 2 | for details on configuring this project to bundle and minify static web assets. */ 3 | body { 4 | padding-top: 50px; 5 | padding-bottom: 20px; 6 | } 7 | 8 | /* Wrapping element */ 9 | /* Set some basic padding to keep content from hitting the edges */ 10 | .body-content { 11 | padding-left: 15px; 12 | padding-right: 15px; 13 | } 14 | 15 | /* Carousel */ 16 | .carousel-caption p { 17 | font-size: 20px; 18 | line-height: 1.4; 19 | } 20 | 21 | /* Make .svg files in the carousel display properly in older browsers */ 22 | .carousel-inner .item img[src$=".svg"] { 23 | width: 100%; 24 | } 25 | 26 | /* QR code generator */ 27 | #qrCode { 28 | margin: 15px; 29 | } 30 | 31 | #job-publish{ 32 | margin-bottom:20px; 33 | } 34 | 35 | /* Hide/rearrange for smaller screens */ 36 | @media screen and (max-width: 767px) { 37 | /* Hide captions */ 38 | .carousel-caption { 39 | display: none; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/css/site.min.css: -------------------------------------------------------------------------------- 1 | body{padding-top:50px;padding-bottom:20px}.body-content{padding-left:15px;padding-right:15px}.carousel-caption p{font-size:20px;line-height:1.4}.carousel-inner .item img[src$=".svg"]{width:100%}#qrCode{margin:15px}@media screen and (max-width:767px){.carousel-caption{display:none}} -------------------------------------------------------------------------------- /Swift.Management/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bosima/Swift/a5978f40c3db39c9970fc05dcb6656d0ebbc4fb1/Swift.Management/wwwroot/favicon.ico -------------------------------------------------------------------------------- /Swift.Management/wwwroot/js/site.js: -------------------------------------------------------------------------------- 1 | // Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification 2 | // for details on configuring this project to bundle and minify static web assets. 3 | 4 | // Write your JavaScript code. 5 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/js/site.min.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bosima/Swift/a5978f40c3db39c9970fc05dcb6656d0ebbc4fb1/Swift.Management/wwwroot/js/site.min.js -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.ar.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Arabic translation for bootstrap-datetimepicker 3 | * Ala' Mohammad 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['ar'] = { 7 | days: ["الأحد", "الاثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت", "الأحد"], 8 | daysShort: ["أحد", "اثنين", "ثلاثاء", "أربعاء", "خميس", "جمعة", "سبت", "أحد"], 9 | daysMin: ["أح", "إث", "ث", "أر", "خ", "ج", "س", "أح"], 10 | months: ["يناير", "فبراير", "مارس", "أبريل", "مايو", "يونيو", "يوليو", "أغسطس", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر"], 11 | monthsShort: ["يناير", "فبراير", "مارس", "أبريل", "مايو", "يونيو", "يوليو", "أغسطس", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر"], 12 | today: "هذا اليوم", 13 | suffix: [], 14 | meridiem: [], 15 | rtl: true 16 | }; 17 | }(jQuery)); 18 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.az.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Azerbaijani translation for bootstrap-datetimepicker 3 | * Konstantin Kaluzhnikov 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['az'] = { 7 | days: ["Bazar", "Bazar ertəsi", "Çərşənbə axşamı", "Çərşənbə", "Cümə axşamı", "Cümə", "Şənbə", "Bazar"], 8 | daysShort: ["B", "Be", "Ça", "Ç", "Ca", "C", "Ş", "B"], 9 | daysMin: ["B", "Be", "Ça", "Ç", "Ca", "C", "Ş", "B"], 10 | months: ["Yanvar", "Fevral", "Mart", "Aprel", "May", "İyun", "İyul", "Avqust", "Sentyabr", "Oktyabr", "Noyabr", "Dekabr"], 11 | monthsShort: ["Yan", "Fev", "Mar", "Apr", "May", "İyun", "İyul", "Avq", "Sen", "Okt", "Noy", "Dek"], 12 | today: "Bugün", 13 | suffix: [], 14 | meridiem: [] 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.bg.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Bulgarian translation for bootstrap-datetimepicker 3 | * Apostol Apostolov 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['bg'] = { 7 | days: ["Неделя", "Понеделник", "Вторник", "Сряда", "Четвъртък", "Петък", "Събота", "Неделя"], 8 | daysShort: ["Нед", "Пон", "Вто", "Сря", "Чет", "Пет", "Съб", "Нед"], 9 | daysMin: ["Н", "П", "В", "С", "Ч", "П", "С", "Н"], 10 | months: ["Януари", "Февруари", "Март", "Април", "Май", "Юни", "Юли", "Август", "Септември", "Октомври", "Ноември", "Декември"], 11 | monthsShort: ["Ян", "Фев", "Мар", "Апр", "Май", "Юни", "Юли", "Авг", "Сеп", "Окт", "Ное", "Дек"], 12 | today: "днес", 13 | suffix: [], 14 | meridiem: [] 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.bn.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Bangla(Bangladesh) translation for bootstrap-datetimepicker 3 | * Mahbub Rabbani 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['bn'] = { 7 | days: ["রবিবার", "সোমবার", "মঙ্গলবার", "বুধবার", "বৃহষ্পতিবার", "শুক্রবার", "শনিবার", "রবিবার"], 8 | daysShort: ["রবি", "সোম", "মঙ্গল", "বুধ", " বৃহঃ", "শুক্র", "শনি", "রবি"], 9 | daysMin: ["রবি", "সোম", "মঙ্গ", "বুধ", "বৃহ", "শুক্র", "শনি", "রবি"], 10 | months: ['জানুয়ারী', 'ফেব্রুয়ারী', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'অগাস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর' ], 11 | monthsShort: ['জানু', 'ফেব্রু', 'মার্চ', 'এপ্রি', 'মে', 'জুন', 'জুলা', 'অগা', 'সেপ্টে', 'অক্টো', 'নভে', 'ডিসে' ], 12 | today: "আজ", 13 | suffix: [], 14 | meridiem: ['পূর্বাহ্ণ', 'অপরাহ্ন'] 15 | }; 16 | }(jQuery)); -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.ca.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Catalan translation for bootstrap-datetimepicker 3 | * J. Garcia 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['ca'] = { 7 | days: ["Diumenge", "Dilluns", "Dimarts", "Dimecres", "Dijous", "Divendres", "Dissabte", "Diumenge"], 8 | daysShort: ["Diu", "Dil", "Dmt", "Dmc", "Dij", "Div", "Dis", "Diu"], 9 | daysMin: ["dg", "dl", "dt", "dc", "dj", "dv", "ds", "dg"], 10 | months: ["Gener", "Febrer", "Març", "Abril", "Maig", "Juny", "Juliol", "Agost", "Setembre", "Octubre", "Novembre", "Desembre"], 11 | monthsShort: ["Gen", "Feb", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Oct", "Nov", "Des"], 12 | today: "Avui", 13 | suffix: [], 14 | meridiem: [] 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.cs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Czech translation for bootstrap-datetimepicker 3 | * Matěj Koubík 4 | * Fixes by Michal Remiš 5 | */ 6 | ;(function($){ 7 | $.fn.datetimepicker.dates['cs'] = { 8 | days: ["Neděle", "Pondělí", "Úterý", "Středa", "Čtvrtek", "Pátek", "Sobota", "Neděle"], 9 | daysShort: ["Ned", "Pon", "Úte", "Stř", "Čtv", "Pát", "Sob", "Ned"], 10 | daysMin: ["Ne", "Po", "Út", "St", "Čt", "Pá", "So", "Ne"], 11 | months: ["Leden", "Únor", "Březen", "Duben", "Květen", "Červen", "Červenec", "Srpen", "Září", "Říjen", "Listopad", "Prosinec"], 12 | monthsShort: ["Led", "Úno", "Bře", "Dub", "Kvě", "Čer", "Čnc", "Srp", "Zář", "Říj", "Lis", "Pro"], 13 | today: "Dnes", 14 | suffix: [], 15 | meridiem: [], 16 | weekStart: 1, 17 | format: "dd.mm.yyyy" 18 | }; 19 | }(jQuery)); 20 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.da.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Danish translation for bootstrap-datetimepicker 3 | * Christian Pedersen 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['da'] = { 7 | days: ["Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag", "Søndag"], 8 | daysShort: ["Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør", "Søn"], 9 | daysMin: ["Sø", "Ma", "Ti", "On", "To", "Fr", "Lø", "Sø"], 10 | months: ["Januar", "Februar", "Marts", "April", "Maj", "Juni", "Juli", "August", "September", "Oktober", "November", "December"], 11 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"], 12 | today: "I Dag", 13 | suffix: [], 14 | meridiem: [] 15 | }; 16 | }(jQuery)); -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.de.js: -------------------------------------------------------------------------------- 1 | /** 2 | * German translation for bootstrap-datetimepicker 3 | * Sam Zurcher 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['de'] = { 7 | days: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag"], 8 | daysShort: ["Son", "Mon", "Die", "Mit", "Don", "Fre", "Sam", "Son"], 9 | daysMin: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"], 10 | months: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"], 11 | monthsShort: ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"], 12 | today: "Heute", 13 | suffix: [], 14 | meridiem: [], 15 | weekStart: 1, 16 | format: "dd.mm.yyyy" 17 | }; 18 | }(jQuery)); 19 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.ee.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Estonian translation for bootstrap-datetimepicker 3 | * Rene Korss 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['ee'] = { 7 | days: ["Pühapäev", "Esmaspäev", "Teisipäev", "Kolmapäev", "Neljapäev", "Reede", "Laupäev", "Pühapäev"], 8 | daysShort: ["P", "E", "T", "K", "N", "R", "L", "P"], 9 | daysMin: ["P", "E", "T", "K", "N", "R", "L", "P"], 10 | months: ["Jaanuar", "Veebruar", "Märts", "Aprill", "Mai", "Juuni", "Juuli", "August", "September", "Oktoober", "November", "Detsember"], 11 | monthsShort: ["Jaan", "Veebr", "Märts", "Apr", "Mai", "Juuni", "Juuli", "Aug", "Sept", "Okt", "Nov", "Dets"], 12 | today: "Täna", 13 | suffix: [], 14 | meridiem: [], 15 | weekStart: 1, 16 | format: "dd.mm.yyyy hh:ii" 17 | }; 18 | }(jQuery)); -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.el.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Greek translation for bootstrap-datetimepicker 3 | */ 4 | ;(function($){ 5 | $.fn.datetimepicker.dates['el'] = { 6 | days: ["Κυριακή", "Δευτέρα", "Τρίτη", "Τετάρτη", "Πέμπτη", "Παρασκευή", "Σάββατο", "Κυριακή"], 7 | daysShort: ["Κυρ", "Δευ", "Τρι", "Τετ", "Πεμ", "Παρ", "Σαβ", "Κυρ"], 8 | daysMin: ["Κυ", "Δε", "Τρ", "Τε", "Πε", "Πα", "Σα", "Κυ"], 9 | months: ["Ιανουάριος", "Φεβρουάριος", "Μάρτιος", "Απρίλιος", "Μάιος", "Ιούνιος", "Ιούλιος", "Αύγουστος", "Σεπτέμβριος", "Οκτώβριος", "Νοέμβριος", "Δεκέμβριος"], 10 | monthsShort: ["Ιαν", "Φεβ", "Μαρ", "Απρ", "Μάι", "Ιουν", "Ιουλ", "Αυγ", "Σεπ", "Οκτ", "Νοε", "Δεκ"], 11 | today: "Σήμερα", 12 | suffix: [], 13 | meridiem: [] 14 | }; 15 | }(jQuery)); -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.es.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Spanish translation for bootstrap-datetimepicker 3 | * Bruno Bonamin 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['es'] = { 7 | days: ["Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado", "Domingo"], 8 | daysShort: ["Dom", "Lun", "Mar", "Mié", "Jue", "Vie", "Sáb", "Dom"], 9 | daysMin: ["Do", "Lu", "Ma", "Mi", "Ju", "Vi", "Sa", "Do"], 10 | months: ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"], 11 | monthsShort: ["Ene", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic"], 12 | today: "Hoy", 13 | suffix: [], 14 | meridiem: [] 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.fi.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Finnish translation for bootstrap-datetimepicker 3 | * Jaakko Salonen 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['fi'] = { 7 | days: ["sunnuntai", "maanantai", "tiistai", "keskiviikko", "torstai", "perjantai", "lauantai", "sunnuntai"], 8 | daysShort: ["sun", "maa", "tii", "kes", "tor", "per", "lau", "sun"], 9 | daysMin: ["su", "ma", "ti", "ke", "to", "pe", "la", "su"], 10 | months: ["tammikuu", "helmikuu", "maaliskuu", "huhtikuu", "toukokuu", "kesäkuu", "heinäkuu", "elokuu", "syyskuu", "lokakuu", "marraskuu", "joulukuu"], 11 | monthsShort: ["tam", "hel", "maa", "huh", "tou", "kes", "hei", "elo", "syy", "lok", "mar", "jou"], 12 | today: "tänään", 13 | suffix: [], 14 | meridiem: [] 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.fr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * French translation for bootstrap-datetimepicker 3 | * Nico Mollet 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['fr'] = { 7 | days: ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche"], 8 | daysShort: ["Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam", "Dim"], 9 | daysMin: ["D", "L", "Ma", "Me", "J", "V", "S", "D"], 10 | months: ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"], 11 | monthsShort: ["Jan", "Fev", "Mar", "Avr", "Mai", "Jui", "Jul", "Aou", "Sep", "Oct", "Nov", "Dec"], 12 | today: "Aujourd'hui", 13 | suffix: [], 14 | meridiem: ["am", "pm"], 15 | weekStart: 1, 16 | format: "dd/mm/yyyy hh:ii" 17 | }; 18 | }(jQuery)); 19 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.he.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Hebrew translation for bootstrap-datetimepicker 3 | * Sagie Maoz 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['he'] = { 7 | days: ["ראשון", "שני", "שלישי", "רביעי", "חמישי", "שישי", "שבת", "ראשון"], 8 | daysShort: ["א", "ב", "ג", "ד", "ה", "ו", "ש", "א"], 9 | daysMin: ["א", "ב", "ג", "ד", "ה", "ו", "ש", "א"], 10 | months: ["ינואר", "פברואר", "מרץ", "אפריל", "מאי", "יוני", "יולי", "אוגוסט", "ספטמבר", "אוקטובר", "נובמבר", "דצמבר"], 11 | monthsShort: ["ינו", "פבר", "מרץ", "אפר", "מאי", "יונ", "יול", "אוג", "ספט", "אוק", "נוב", "דצמ"], 12 | today: "היום", 13 | suffix: [], 14 | meridiem: [], 15 | rtl: true 16 | }; 17 | }(jQuery)); 18 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.hr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Croatian localisation 3 | */ 4 | ;(function($){ 5 | $.fn.datetimepicker.dates['hr'] = { 6 | days: ["Nedjelja", "Ponedjelja", "Utorak", "Srijeda", "Četrtak", "Petak", "Subota", "Nedjelja"], 7 | daysShort: ["Ned", "Pon", "Uto", "Srr", "Čet", "Pet", "Sub", "Ned"], 8 | daysMin: ["Ne", "Po", "Ut", "Sr", "Če", "Pe", "Su", "Ne"], 9 | months: ["Siječanj", "Veljača", "Ožujak", "Travanj", "Svibanj", "Lipanj", "Srpanj", "Kolovoz", "Rujan", "Listopad", "Studeni", "Prosinac"], 10 | monthsShort: ["Sije", "Velj", "Ožu", "Tra", "Svi", "Lip", "Jul", "Kol", "Ruj", "Lis", "Stu", "Pro"], 11 | today: "Danas", 12 | suffix: [], 13 | meridiem: [] 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.hu.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Hungarian translation for bootstrap-datetimepicker 3 | * darevish 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['hu'] = { 7 | days: ["Vasárnap", "Hétfő", "Kedd", "Szerda", "Csütörtök", "Péntek", "Szombat", "Vasárnap"], 8 | daysShort: ["Vas", "Hét", "Ked", "Sze", "Csü", "Pén", "Szo", "Vas"], 9 | daysMin: ["V", "H", "K", "Sze", "Cs", "P", "Szo", "V"], 10 | months: ["Január", "Február", "Március", "Április", "Május", "Június", "Július", "Augusztus", "Szeptember", "Október", "November", "December"], 11 | monthsShort: ["Jan", "Feb", "Már", "Ápr", "Máj", "Jún", "Júl", "Aug", "Sze", "Okt", "Nov", "Dec"], 12 | today: "Ma", 13 | suffix: [], 14 | meridiem: [], 15 | weekStart: 1 16 | }; 17 | }(jQuery)); 18 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.hy.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Armenian translation for bootstrap-datepicker 3 | * Hayk Chamyan 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['hy'] = { 7 | days: ["Կիրակի", "Երկուշաբթի", "Երեքշաբթի", "Չորեքշաբթի", "Հինգշաբթի", "Ուրբաթ", "Շաբաթ", "Կիրակի"], 8 | daysShort: ["Կիր", "Երկ", "Երք", "Չոր", "Հնգ", "Ուր", "Շաբ", "Կիր"], 9 | daysMin: ["Կի", "Եկ", "Եք", "Չո", "Հի", "Ու", "Շա", "Կի"], 10 | months: ["Հունվար", "Փետրվար", "Մարտ", "Ապրիլ", "Մայիս", "Հունիս", "Հուլիս", "Օգոստոս", "Սեպտեմբեր", "Հոկտեմբեր", "Նոյեմբեր", "Դեկտեմբեր"], 11 | monthsShort: ["Հնվ", "Փետ", "Մար", "Ապր", "Մայ", "Հուն", "Հուլ", "Օգս", "Սեպ", "Հոկ", "Նոյ", "Դեկ"], 12 | today: "Այսօր", 13 | suffix: [], 14 | meridiem: [] 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.id.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Bahasa translation for bootstrap-datetimepicker 3 | * Azwar Akbar 4 | * Addtional by Yulian Sutopo 5 | */ 6 | ;(function($){ 7 | $.fn.datetimepicker.dates['id'] = { 8 | days: ["Minggu", "Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu", "Minggu"], 9 | daysShort: ["Mng", "Sen", "Sel", "Rab", "Kam", "Jum", "Sab", "Mng"], 10 | daysMin: ["Mg", "Sn", "Sl", "Ra", "Ka", "Ju", "Sa", "Mg"], 11 | months: ["Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember"], 12 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Ags", "Sep", "Okt", "Nov", "Des"], 13 | today: "Hari Ini", 14 | suffix: [], 15 | meridiem: [], 16 | weekStart: 1, 17 | format: "dd/mm/yyyy hh:ii:ss" 18 | }; 19 | }(jQuery)); 20 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.is.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Icelandic translation for bootstrap-datetimepicker 3 | * Hinrik Örn Sigurðsson 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['is'] = { 7 | days: ["Sunnudagur", "Mánudagur", "Þriðjudagur", "Miðvikudagur", "Fimmtudagur", "Föstudagur", "Laugardagur", "Sunnudagur"], 8 | daysShort: ["Sun", "Mán", "Þri", "Mið", "Fim", "Fös", "Lau", "Sun"], 9 | daysMin: ["Su", "Má", "Þr", "Mi", "Fi", "Fö", "La", "Su"], 10 | months: ["Janúar", "Febrúar", "Mars", "Apríl", "Maí", "Júní", "Júlí", "Ágúst", "September", "Október", "Nóvember", "Desember"], 11 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maí", "Jún", "Júl", "Ágú", "Sep", "Okt", "Nóv", "Des"], 12 | today: "Í Dag", 13 | suffix: [], 14 | meridiem: [] 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.it.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Italian translation for bootstrap-datetimepicker 3 | * Enrico Rubboli 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['it'] = { 7 | days: ["Domenica", "Lunedi", "Martedi", "Mercoledi", "Giovedi", "Venerdi", "Sabato", "Domenica"], 8 | daysShort: ["Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab", "Dom"], 9 | daysMin: ["Do", "Lu", "Ma", "Me", "Gi", "Ve", "Sa", "Do"], 10 | months: ["Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre"], 11 | monthsShort: ["Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"], 12 | today: "Oggi", 13 | suffix: [], 14 | meridiem: [], 15 | weekStart: 1, 16 | format: "dd/mm/yyyy hh:ii:ss" 17 | }; 18 | }(jQuery)); 19 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.ja.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Japanese translation for bootstrap-datetimepicker 3 | * Norio Suzuki 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['ja'] = { 7 | days: ["日曜", "月曜", "火曜", "水曜", "木曜", "金曜", "土曜", "日曜"], 8 | daysShort: ["日", "月", "火", "水", "木", "金", "土", "日"], 9 | daysMin: ["日", "月", "火", "水", "木", "金", "土", "日"], 10 | months: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"], 11 | monthsShort: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"], 12 | today: "今日", 13 | suffix: [], 14 | meridiem: [] 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.ka.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Georgian translation for bootstrap-datetimepicker 3 | * Zura Jijavadze 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['ka'] = { 7 | days: ["კვირა", "ორშაბათი", "სამშაბათი", "ოთხშაბათი", "ხუთშაბათი", "პარასკევი", "შაბათი", "კვირა"], 8 | daysShort: ["კვი", "ორშ", "სამ", "ოთხ", "ხუთ", "პარ", "შაბ", "კვი"], 9 | daysMin: ["კვ", "ორ", "სა", "ოთ", "ხუ", "პა", "შა", "კვ"], 10 | months: ["იანვარი", "თებერვალი", "მარტი", "აპრილი", "მაისი", "ივნისი", "ივლისი", "აგვისტო", "სექტემბერი", "ოქტომბერი", "ნოემბერი", "დეკემბერი"], 11 | monthsShort: ["იან", "თებ", "მარ", "აპრ", "მაი", "ივნ", "ივლ", "აგვ", "სექ", "ოქტ", "ნოე", "დეკ"], 12 | today: "დღეს", 13 | suffix: [], 14 | meridiem: [] 15 | }; 16 | }(jQuery)); -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.ko.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Korean translation for bootstrap-datetimepicker 3 | * Gu Youn 4 | * Baekjoon Choi 5 | */ 6 | ;(function($){ 7 | $.fn.datetimepicker.dates['ko'] = { 8 | days: ["일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일", "일요일"], 9 | daysShort: ["일", "월", "화", "수", "목", "금", "토", "일"], 10 | daysMin: ["일", "월", "화", "수", "목", "금", "토", "일"], 11 | months: ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"], 12 | monthsShort: ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"], 13 | suffix: [], 14 | meridiem: ["오전", "오후"], 15 | today: "오늘", 16 | }; 17 | }(jQuery)); 18 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.lt.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Lithuanian translation for bootstrap-datetimepicker 3 | * Šarūnas Gliebus 4 | */ 5 | 6 | ;(function($){ 7 | $.fn.datetimepicker.dates['lt'] = { 8 | days: ["Sekmadienis", "Pirmadienis", "Antradienis", "Trečiadienis", "Ketvirtadienis", "Penktadienis", "Šeštadienis", "Sekmadienis"], 9 | daysShort: ["S", "Pr", "A", "T", "K", "Pn", "Š", "S"], 10 | daysMin: ["Sk", "Pr", "An", "Tr", "Ke", "Pn", "Št", "Sk"], 11 | months: ["Sausis", "Vasaris", "Kovas", "Balandis", "Gegužė", "Birželis", "Liepa", "Rugpjūtis", "Rugsėjis", "Spalis", "Lapkritis", "Gruodis"], 12 | monthsShort: ["Sau", "Vas", "Kov", "Bal", "Geg", "Bir", "Lie", "Rugp", "Rugs", "Spa", "Lap", "Gru"], 13 | today: "Šiandien", 14 | suffix: [], 15 | meridiem: [], 16 | weekStart: 1 17 | }; 18 | }(jQuery)); 19 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.lv.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Latvian translation for bootstrap-datetimepicker 3 | * Artis Avotins 4 | */ 5 | 6 | ;(function($){ 7 | $.fn.datetimepicker.dates['lv'] = { 8 | days: ["Svētdiena", "Pirmdiena", "Otrdiena", "Trešdiena", "Ceturtdiena", "Piektdiena", "Sestdiena", "Svētdiena"], 9 | daysShort: ["Sv", "P", "O", "T", "C", "Pk", "S", "Sv"], 10 | daysMin: ["Sv", "Pr", "Ot", "Tr", "Ce", "Pk", "St", "Sv"], 11 | months: ["Janvāris", "Februāris", "Marts", "Aprīlis", "Maijs", "Jūnijs", "Jūlijs", "Augusts", "Septembris", "Oktobris", "Novembris", "Decembris"], 12 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mai", "Jūn", "Jūl", "Aug", "Sep", "Okt", "Nov", "Dec."], 13 | today: "Šodien", 14 | suffix: [], 15 | meridiem: [], 16 | weekStart: 1 17 | }; 18 | }(jQuery)); -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.ms.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Malay translation for bootstrap-datetimepicker 3 | * Ateman Faiz 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['ms'] = { 7 | days: ["Ahad", "Isnin", "Selasa", "Rabu", "Khamis", "Jumaat", "Sabtu", "Ahad"], 8 | daysShort: ["Aha", "Isn", "Sel", "Rab", "Kha", "Jum", "Sab", "Aha"], 9 | daysMin: ["Ah", "Is", "Se", "Ra", "Kh", "Ju", "Sa", "Ah"], 10 | months: ["Januari", "Februari", "Mac", "April", "Mei", "Jun", "Julai", "Ogos", "September", "Oktober", "November", "Disember"], 11 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Ogo", "Sep", "Okt", "Nov", "Dis"], 12 | today: "Hari Ini", 13 | suffix: [], 14 | meridiem: [] 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.nb.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Norwegian (bokmål) translation for bootstrap-datetimepicker 3 | * Fredrik Sundmyhr 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['nb'] = { 7 | days: ["Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag", "Søndag"], 8 | daysShort: ["Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør", "Søn"], 9 | daysMin: ["Sø", "Ma", "Ti", "On", "To", "Fr", "Lø", "Sø"], 10 | months: ["Januar", "Februar", "Mars", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Desember"], 11 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Des"], 12 | today: "I Dag", 13 | suffix: [], 14 | meridiem: [] 15 | }; 16 | }(jQuery)); -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.nl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Dutch translation for bootstrap-datetimepicker 3 | * Reinier Goltstein 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['nl'] = { 7 | days: ["Zondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag", "Zondag"], 8 | daysShort: ["Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za", "Zo"], 9 | daysMin: ["Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za", "Zo"], 10 | months: ["Januari", "Februari", "Maart", "April", "Mei", "Juni", "Juli", "Augustus", "September", "Oktober", "November", "December"], 11 | monthsShort: ["Jan", "Feb", "Mrt", "Apr", "Mei", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"], 12 | today: "Vandaag", 13 | suffix: [], 14 | meridiem: [] 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.no.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Norwegian translation for bootstrap-datetimepicker 3 | * Rune Warhuus 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['no'] = { 7 | days: ["Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag", "Søndag"], 8 | daysShort: ["Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør", "Søn"], 9 | daysMin: ["Sø", "Ma", "Ti", "On", "To", "Fr", "Lø", "Sø"], 10 | months: ["Januar", "Februar", "Mars", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Desember"], 11 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Des"], 12 | today: "I Dag", 13 | suffix: [], 14 | meridiem: [] 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.pl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Polish translation for bootstrap-datetimepicker 3 | * Robert 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['pl'] = { 7 | days: ["Niedziela", "Poniedziałek", "Wtorek", "Środa", "Czwartek", "Piątek", "Sobota", "Niedziela"], 8 | daysShort: ["Nie", "Pn", "Wt", "Śr", "Czw", "Pt", "So", "Nie"], 9 | daysMin: ["N", "Pn", "Wt", "Śr", "Cz", "Pt", "So", "N"], 10 | months: ["Styczeń", "Luty", "Marzec", "Kwiecień", "Maj", "Czerwiec", "Lipiec", "Sierpień", "Wrzesień", "Październik", "Listopad", "Grudzień"], 11 | monthsShort: ["Sty", "Lu", "Mar", "Kw", "Maj", "Cze", "Lip", "Sie", "Wrz", "Pa", "Lis", "Gru"], 12 | today: "Dzisiaj", 13 | suffix: [], 14 | meridiem: [], 15 | weekStart: 1 16 | }; 17 | }(jQuery)); 18 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.pt-BR.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Brazilian translation for bootstrap-datetimepicker 3 | * Cauan Cabral 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['pt-BR'] = { 7 | format: 'dd/mm/yyyy', 8 | days: ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado", "Domingo"], 9 | daysShort: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb", "Dom"], 10 | daysMin: ["Do", "Se", "Te", "Qu", "Qu", "Se", "Sa", "Do"], 11 | months: ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"], 12 | monthsShort: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"], 13 | today: "Hoje", 14 | suffix: [], 15 | meridiem: [] 16 | }; 17 | }(jQuery)); 18 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.pt.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Portuguese translation for bootstrap-datetimepicker 3 | * Original code: Cauan Cabral 4 | * Tiago Melo 5 | */ 6 | ;(function($){ 7 | $.fn.datetimepicker.dates['pt'] = { 8 | days: ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado", "Domingo"], 9 | daysShort: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb", "Dom"], 10 | daysMin: ["Do", "Se", "Te", "Qu", "Qu", "Se", "Sa", "Do"], 11 | months: ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"], 12 | monthsShort: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"], 13 | suffix: [], 14 | meridiem: [], 15 | today: "Hoje" 16 | }; 17 | }(jQuery)); 18 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.ro.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Romanian translation for bootstrap-datetimepicker 3 | * Cristian Vasile 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['ro'] = { 7 | days: ["Duminică", "Luni", "Marţi", "Miercuri", "Joi", "Vineri", "Sâmbătă", "Duminică"], 8 | daysShort: ["Dum", "Lun", "Mar", "Mie", "Joi", "Vin", "Sâm", "Dum"], 9 | daysMin: ["Du", "Lu", "Ma", "Mi", "Jo", "Vi", "Sâ", "Du"], 10 | months: ["Ianuarie", "Februarie", "Martie", "Aprilie", "Mai", "Iunie", "Iulie", "August", "Septembrie", "Octombrie", "Noiembrie", "Decembrie"], 11 | monthsShort: ["Ian", "Feb", "Mar", "Apr", "Mai", "Iun", "Iul", "Aug", "Sep", "Oct", "Nov", "Dec"], 12 | today: "Astăzi", 13 | suffix: [], 14 | meridiem: [], 15 | weekStart: 1 16 | }; 17 | }(jQuery)); 18 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.rs-latin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Serbian latin translation for bootstrap-datetimepicker 3 | * Bojan Milosavlević 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['rs'] = { 7 | days: ["Nedelja","Ponedeljak", "Utorak", "Sreda", "Četvrtak", "Petak", "Subota", "Nedelja"], 8 | daysShort: ["Ned", "Pon", "Uto", "Sre", "Čet", "Pet", "Sub", "Ned"], 9 | daysMin: ["N", "Po", "U", "Sr", "Č", "Pe", "Su", "N"], 10 | months: ["Januar", "Februar", "Mart", "April", "Maj", "Jun", "Jul", "Avgust", "Septembar", "Oktobar", "Novembar", "Decembar"], 11 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Avg", "Sep", "Okt", "Nov", "Dec"], 12 | today: "Danas", 13 | suffix: [], 14 | meridiem: [] 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.rs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Serbian cyrillic translation for bootstrap-datetimepicker 3 | * Bojan Milosavlević 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['rs'] = { 7 | days: ["Недеља","Понедељак", "Уторак", "Среда", "Четвртак", "Петак", "Субота", "Недеља"], 8 | daysShort: ["Нед", "Пон", "Уто", "Сре", "Чет", "Пет", "Суб", "Нед"], 9 | daysMin: ["Н", "По", "У", "Ср", "Ч", "Пе", "Су", "Н"], 10 | months: ["Јануар", "Фебруар", "Март", "Април", "Мај", "Јун", "Јул", "Август", "Септембар", "Октобар", "Новембар", "Децембар"], 11 | monthsShort: ["Јан", "Феб", "Мар", "Апр", "Мај", "Јун", "Јул", "Авг", "Сеп", "Окт", "Нов", "Дец"], 12 | today: "Данас", 13 | suffix: [], 14 | meridiem: [] 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.ru.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Russian translation for bootstrap-datetimepicker 3 | * Victor Taranenko 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['ru'] = { 7 | days: ["Воскресенье", "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота", "Воскресенье"], 8 | daysShort: ["Вск", "Пнд", "Втр", "Срд", "Чтв", "Птн", "Суб", "Вск"], 9 | daysMin: ["Вс", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Вс"], 10 | months: ["Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь"], 11 | monthsShort: ["Янв", "Фев", "Мар", "Апр", "Май", "Июн", "Июл", "Авг", "Сен", "Окт", "Ноя", "Дек"], 12 | today: "Сегодня", 13 | suffix: [], 14 | meridiem: [] 15 | }; 16 | }(jQuery)); -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.sk.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Slovak translation for bootstrap-datetimepicker 3 | * Marek Lichtner 4 | * Fixes by Michal Remiš 5 | */ 6 | ;(function($){ 7 | $.fn.datetimepicker.dates["sk"] = { 8 | days: ["Nedeľa", "Pondelok", "Utorok", "Streda", "Štvrtok", "Piatok", "Sobota", "Nedeľa"], 9 | daysShort: ["Ned", "Pon", "Uto", "Str", "Štv", "Pia", "Sob", "Ned"], 10 | daysMin: ["Ne", "Po", "Ut", "St", "Št", "Pi", "So", "Ne"], 11 | months: ["Január", "Február", "Marec", "Apríl", "Máj", "Jún", "Júl", "August", "September", "Október", "November", "December"], 12 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Máj", "Jún", "Júl", "Aug", "Sep", "Okt", "Nov", "Dec"], 13 | today: "Dnes", 14 | suffix: [], 15 | meridiem: [], 16 | weekStart: 1, 17 | format: "dd.mm.yyyy" 18 | }; 19 | }(jQuery)); 20 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.sl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Slovene translation for bootstrap-datetimepicker 3 | * Gregor Rudolf 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['sl'] = { 7 | days: ["Nedelja", "Ponedeljek", "Torek", "Sreda", "Četrtek", "Petek", "Sobota", "Nedelja"], 8 | daysShort: ["Ned", "Pon", "Tor", "Sre", "Čet", "Pet", "Sob", "Ned"], 9 | daysMin: ["Ne", "Po", "To", "Sr", "Če", "Pe", "So", "Ne"], 10 | months: ["Januar", "Februar", "Marec", "April", "Maj", "Junij", "Julij", "Avgust", "September", "Oktober", "November", "December"], 11 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Avg", "Sep", "Okt", "Nov", "Dec"], 12 | today: "Danes", 13 | suffix: [], 14 | meridiem: [] 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.sv.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Swedish translation for bootstrap-datetimepicker 3 | * Patrik Ragnarsson 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['sv'] = { 7 | days: ["Söndag", "Måndag", "Tisdag", "Onsdag", "Torsdag", "Fredag", "Lördag", "Söndag"], 8 | daysShort: ["Sön", "Mån", "Tis", "Ons", "Tor", "Fre", "Lör", "Sön"], 9 | daysMin: ["Sö", "Må", "Ti", "On", "To", "Fr", "Lö", "Sö"], 10 | months: ["Januari", "Februari", "Mars", "April", "Maj", "Juni", "Juli", "Augusti", "September", "Oktober", "November", "December"], 11 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"], 12 | today: "I Dag", 13 | suffix: [], 14 | meridiem: [] 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.sw.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Swahili translation for bootstrap-datetimepicker 3 | * Edwin Mugendi 4 | * Source: http://scriptsource.org/cms/scripts/page.php?item_id=entry_detail&uid=xnfaqyzcku 5 | */ 6 | ;(function($){ 7 | $.fn.datetimepicker.dates['sw'] = { 8 | days: ["Jumapili", "Jumatatu", "Jumanne", "Jumatano", "Alhamisi", "Ijumaa", "Jumamosi", "Jumapili"], 9 | daysShort: ["J2", "J3", "J4", "J5", "Alh", "Ij", "J1", "J2"], 10 | daysMin: ["2", "3", "4", "5", "A", "I", "1", "2"], 11 | months: ["Januari", "Februari", "Machi", "Aprili", "Mei", "Juni", "Julai", "Agosti", "Septemba", "Oktoba", "Novemba", "Desemba"], 12 | monthsShort: ["Jan", "Feb", "Mac", "Apr", "Mei", "Jun", "Jul", "Ago", "Sep", "Okt", "Nov", "Des"], 13 | today: "Leo", 14 | suffix: [], 15 | meridiem: [] 16 | }; 17 | }(jQuery)); 18 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.th.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Thai translation for bootstrap-datetimepicker 3 | * Suchau Jiraprapot 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['th'] = { 7 | days: ["อาทิตย์", "จันทร์", "อังคาร", "พุธ", "พฤหัส", "ศุกร์", "เสาร์", "อาทิตย์"], 8 | daysShort: ["อา", "จ", "อ", "พ", "พฤ", "ศ", "ส", "อา"], 9 | daysMin: ["อา", "จ", "อ", "พ", "พฤ", "ศ", "ส", "อา"], 10 | months: ["มกราคม", "กุมภาพันธ์", "มีนาคม", "เมษายน", "พฤษภาคม", "มิถุนายน", "กรกฎาคม", "สิงหาคม", "กันยายน", "ตุลาคม", "พฤศจิกายน", "ธันวาคม"], 11 | monthsShort: ["ม.ค.", "ก.พ.", "มี.ค.", "เม.ย.", "พ.ค.", "มิ.ย.", "ก.ค.", "ส.ค.", "ก.ย.", "ต.ค.", "พ.ย.", "ธ.ค."], 12 | today: "วันนี้", 13 | suffix: [], 14 | meridiem: [] 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.tr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Turkish translation for bootstrap-datetimepicker 3 | * Serkan Algur 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['tr'] = { 7 | days: ["Pazar", "Pazartesi", "Salı", "Çarşamba", "Perşembe", "Cuma", "Cumartesi", "Pazar"], 8 | daysShort: ["Pz", "Pzt", "Sal", "Çrş", "Prş", "Cu", "Cts", "Pz"], 9 | daysMin: ["Pz", "Pzt", "Sa", "Çr", "Pr", "Cu", "Ct", "Pz"], 10 | months: ["Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık"], 11 | monthsShort: ["Oca", "Şub", "Mar", "Nis", "May", "Haz", "Tem", "Ağu", "Eyl", "Eki", "Kas", "Ara"], 12 | today: "Bugün", 13 | suffix: [], 14 | meridiem: [] 15 | }; 16 | }(jQuery)); 17 | 18 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.ua.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Ukrainian translation for bootstrap-datepicker 3 | * Igor Polynets 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['ua'] = { 7 | days: ["Неділя", "Понеділок", "Вівторок", "Середа", "Четверг", "П'ятниця", "Субота", "Неділя"], 8 | daysShort: ["Нед", "Пнд", "Втр", "Срд", "Чтв", "Птн", "Суб", "Нед"], 9 | daysMin: ["Нд", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Нд"], 10 | months: ["Cічень", "Лютий", "Березень", "Квітень", "Травень", "Червень", "Липень", "Серпень", "Вересень", "Жовтень", "Листопад", "Грудень"], 11 | monthsShort: ["Січ", "Лют", "Бер", "Квт", "Трв", "Чер", "Лип", "Сер", "Вер", "Жов", "Лис", "Грд"], 12 | today: "Сьогодні", 13 | weekStart: 1 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.uk.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Ukrainian translation for bootstrap-datetimepicker 3 | * Andrey Vityuk 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['uk'] = { 7 | days: ["Неділя", "Понеділок", "Вівторок", "Середа", "Четвер", "П'ятниця", "Субота", "Неділя"], 8 | daysShort: ["Нед", "Пнд", "Втр", "Срд", "Чтв", "Птн", "Суб", "Нед"], 9 | daysMin: ["Нд", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Нд"], 10 | months: ["Січень", "Лютий", "Березень", "Квітень", "Травень", "Червень", "Липень", "Серпень", "Вересень", "Жовтень", "Листопад", "Грудень"], 11 | monthsShort: ["Січ", "Лют", "Бер", "Кві", "Тра", "Чер", "Лип", "Сер", "Вер", "Жов", "Лис", "Гру"], 12 | today: "Сьогодні", 13 | suffix: [], 14 | meridiem: [] 15 | }; 16 | }(jQuery)); -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.zh-CN.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Simplified Chinese translation for bootstrap-datetimepicker 3 | * Yuan Cheung 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['zh-CN'] = { 7 | days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"], 8 | daysShort: ["周日", "周一", "周二", "周三", "周四", "周五", "周六", "周日"], 9 | daysMin: ["日", "一", "二", "三", "四", "五", "六", "日"], 10 | months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], 11 | monthsShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], 12 | today: "今天", 13 | suffix: [], 14 | meridiem: ["上午", "下午"] 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.zh-TW.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Traditional Chinese translation for bootstrap-datetimepicker 3 | * Rung-Sheng Jang 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['zh-TW'] = { 7 | days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"], 8 | daysShort: ["周日", "周一", "周二", "周三", "周四", "周五", "周六", "周日"], 9 | daysMin: ["日", "一", "二", "三", "四", "五", "六", "日"], 10 | months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], 11 | monthsShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], 12 | today: "今天", 13 | suffix: [], 14 | meridiem: ["上午", "下午"] 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at kartikv2@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Prerequisites 2 | 3 | - [ ] I have searched for similar issues in both open and closed tickets and cannot find a duplicate. 4 | - [ ] The issue still exists against the latest `master` branch of bootstrap-fileinput. 5 | - [ ] This is not an usage question. I confirm having read the plugin [documentation](http://plugins.krajee.com/file-input) and [demos](http://plugins.krajee.com/file-input/demo). 6 | - [ ] This is not a general programming / coding question. (Those should be directed to the [webtips Q & A forum](http://webtips.krajee.com/questions)). 7 | - [ ] I have attempted to find the simplest possible steps to reproduce the issue. 8 | - [ ] I have included a failing test as a pull request (Optional). 9 | 10 | ## Steps to reproduce the issue 11 | 12 | 1. 13 | 2. 14 | 3. 15 | 16 | ## Expected behavior and actual behavior 17 | 18 | When I follow those steps, I see... 19 | 20 | I was expecting... 21 | 22 | ## Environment 23 | 24 | Browsers 25 | 26 | - [ ] Google Chrome 27 | - [ ] Mozilla Firefox 28 | - [ ] Internet Explorer 29 | - [ ] Safari 30 | 31 | Operating System 32 | 33 | - [ ] Windows 34 | - [ ] Mac OS X 35 | - [ ] Linux 36 | - [ ] Mobile 37 | 38 | Libraries 39 | 40 | - jQuery version: 41 | - bootstrap-fileinput version: 42 | 43 | ## Isolating the problem 44 | 45 | - [ ] This bug happens [on the plugin demos page](http://plugins.krajee.com/file-input/demo) 46 | - [ ] The bug happens consistently across all tested browsers 47 | - [ ] This bug happens when using bootstrap-fileinput without other plugins 48 | - [ ] I can reproduce this bug in [a jsbin](https://jsbin.com/) 49 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Scope 2 | This pull request includes a 3 | 4 | - [ ] Bug fix 5 | - [ ] New feature 6 | - [ ] Translation 7 | 8 | ## Changes 9 | The following changes were made 10 | 11 | - 12 | - 13 | - 14 | 15 | ## Related Issues 16 | If this is related to an existing ticket, include a link to it as well. -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 - 2018, Kartik Visweswaran 2 | Krajee.com 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above copyright notice, this 12 | list of conditions and the following disclaimer in the documentation and/or 13 | other materials provided with the distribution. 14 | 15 | * Neither the names of Kartik Visweswaran or Krajee nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 23 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 26 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bootstrap-fileinput", 3 | "version": "4.5.2", 4 | "homepage": "https://github.com/kartik-v/bootstrap-fileinput", 5 | "authors": [ 6 | "Kartik Visweswaran " 7 | ], 8 | "description": "An enhanced HTML 5 file input for Bootstrap 3.x with file preview, multiple selection, ajax uploads, and more features.", 9 | "main": [ 10 | "./css/fileinput.min.css", 11 | "./js/fileinput.min.js" 12 | ], 13 | "keywords": [ 14 | "bootstrap", 15 | "file", 16 | "input", 17 | "preview", 18 | "image", 19 | "upload", 20 | "ajax", 21 | "multiple", 22 | "delete", 23 | "progress", 24 | "gallery" 25 | ], 26 | "dependencies": { 27 | "jquery": ">= 1.9.0", 28 | "bootstrap": ">= 3.0.0" 29 | }, 30 | "license": "BSD-3-Clause", 31 | "ignore": [ 32 | "**/.*", 33 | "node_modules", 34 | "composer.json", 35 | "examples", 36 | "bower_components", 37 | "test", 38 | "tests" 39 | ] 40 | } 41 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kartik-v/bootstrap-fileinput", 3 | "description": "An enhanced HTML 5 file input for Bootstrap 3.x with features for file preview for many file types, multiple selection, ajax uploads, and more.", 4 | "keywords": [ 5 | "bootstrap", 6 | "jquery", 7 | "file", 8 | "input", 9 | "preview", 10 | "upload", 11 | "image", 12 | "multiple", 13 | "ajax", 14 | "delete", 15 | "progress" 16 | ], 17 | "homepage": "https://github.com/kartik-v/bootstrap-fileinput", 18 | "license": "BSD-3-Clause", 19 | "authors": [ 20 | { 21 | "name": "Kartik Visweswaran", 22 | "email": "kartikv2@gmail.com", 23 | "homepage": "http://www.krajee.com/" 24 | } 25 | ], 26 | "autoload": { 27 | "psr-4": { 28 | "kartik\\plugins\\fileinput\\": "" 29 | } 30 | }, 31 | "extra": { 32 | "branch-alias": { 33 | "dev-master": "4.5.x-dev" 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/css/fileinput-rtl.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * bootstrap-fileinput v4.5.2 3 | * http://plugins.krajee.com/file-input 4 | * 5 | * Krajee RTL (Right To Left) default styling for bootstrap-fileinput. 6 | * 7 | * Author: Kartik Visweswaran 8 | * Copyright: 2014 - 2018, Kartik Visweswaran, Krajee.com 9 | * 10 | * Licensed under the BSD 3-Clause 11 | * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md 12 | */ 13 | .kv-rtl .close, .kv-rtl .krajee-default .file-actions, .kv-rtl .krajee-default .file-other-error { 14 | float: left; 15 | } 16 | 17 | .kv-rtl .krajee-default.file-preview-frame, .kv-rtl .krajee-default .file-drag-handle, .kv-rtl .krajee-default .file-upload-indicator { 18 | float: right; 19 | } 20 | 21 | .kv-rtl .file-zoom-dialog, .kv-rtl .file-error-message pre, .kv-rtl .file-error-message ul { 22 | text-align: right; 23 | } 24 | 25 | .kv-rtl { 26 | direction: rtl; 27 | } 28 | 29 | .kv-rtl .floating-buttons { 30 | left: 10px; 31 | right: auto; 32 | } 33 | 34 | .kv-rtl .floating-buttons .btn-kv { 35 | margin-left: 0; 36 | margin-right: 3px; 37 | } 38 | 39 | .kv-rtl .file-caption-icon { 40 | left: auto; 41 | right: 8px; 42 | } 43 | 44 | .kv-rtl .file-drop-zone { 45 | margin: 12px 12px 12px 15px; 46 | } 47 | 48 | .kv-rtl .btn-prev { 49 | right: 1px; 50 | left: auto; 51 | } 52 | 53 | .kv-rtl .btn-next { 54 | left: 1px; 55 | right: auto; 56 | } 57 | 58 | .kv-rtl .pull-right, .kv-rtl .float-right { 59 | float: left !important; 60 | } 61 | 62 | .kv-rtl .pull-left, .kv-rtl .float-left { 63 | float: right !important; 64 | } 65 | 66 | .kv-rtl .kv-zoom-title { 67 | direction: ltr; 68 | } 69 | 70 | .kv-rtl .krajee-default.file-preview-frame { 71 | box-shadow: -1px 1px 5px 0 #a2958a; 72 | } 73 | 74 | .kv-rtl .krajee-default.file-preview-frame:not(.file-preview-error):hover { 75 | box-shadow: -3px 3px 5px 0 #333; 76 | } 77 | 78 | .kv-rtl .kv-zoom-actions .btn-kv { 79 | margin-left: 0; 80 | margin-right: 3px; 81 | } 82 | 83 | .kv-rtl .file-caption.icon-visible .file-caption-name { 84 | padding-left: 0; 85 | padding-right: 15px; 86 | } 87 | 88 | .kv-rtl .input-group-btn > .btn:last-child { 89 | border-radius: 4px 0 0 4px; 90 | } 91 | 92 | .kv-rtl .input-group .form-control:first-child { 93 | border-radius: 0 4px 4px 0; 94 | } 95 | 96 | .kv-rtl .btn-file input[type=file] { 97 | left: auto; 98 | right: 0; 99 | text-align: left; 100 | background: none repeat scroll 100% 0 transparent; 101 | } -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/css/fileinput-rtl.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * bootstrap-fileinput v4.5.2 3 | * http://plugins.krajee.com/file-input 4 | * 5 | * Krajee RTL (Right To Left) default styling for bootstrap-fileinput. 6 | * 7 | * Author: Kartik Visweswaran 8 | * Copyright: 2014 - 2018, Kartik Visweswaran, Krajee.com 9 | * 10 | * Licensed under the BSD 3-Clause 11 | * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md 12 | */.kv-rtl .close,.kv-rtl .krajee-default .file-actions,.kv-rtl .krajee-default .file-other-error{float:left}.kv-rtl .krajee-default .file-drag-handle,.kv-rtl .krajee-default .file-upload-indicator,.kv-rtl .krajee-default.file-preview-frame{float:right}.kv-rtl .file-error-message pre,.kv-rtl .file-error-message ul,.kv-rtl .file-zoom-dialog{text-align:right}.kv-rtl{direction:rtl}.kv-rtl .floating-buttons{left:10px;right:auto}.kv-rtl .floating-buttons .btn-kv{margin-left:0;margin-right:3px}.kv-rtl .file-caption-icon{left:auto;right:8px}.kv-rtl .file-drop-zone{margin:12px 12px 12px 15px}.kv-rtl .btn-prev{right:1px;left:auto}.kv-rtl .btn-next{left:1px;right:auto}.kv-rtl .float-right,.kv-rtl .pull-right{float:left!important}.kv-rtl .float-left,.kv-rtl .pull-left{float:right!important}.kv-rtl .kv-zoom-title{direction:ltr}.kv-rtl .krajee-default.file-preview-frame{box-shadow:-1px 1px 5px 0 #a2958a}.kv-rtl .krajee-default.file-preview-frame:not(.file-preview-error):hover{box-shadow:-3px 3px 5px 0 #333}.kv-rtl .kv-zoom-actions .btn-kv{margin-left:0;margin-right:3px}.kv-rtl .file-caption.icon-visible .file-caption-name{padding-left:0;padding-right:15px}.kv-rtl .input-group-btn>.btn:last-child{border-radius:4px 0 0 4px}.kv-rtl .input-group .form-control:first-child{border-radius:0 4px 4px 0}.kv-rtl .btn-file input[type=file]{left:auto;right:0;text-align:left;background:100% 0 none} -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/img/loading-sm.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bosima/Swift/a5978f40c3db39c9970fc05dcb6656d0ebbc4fb1/Swift.Management/wwwroot/lib/bootstrap-fileinput/img/loading-sm.gif -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/img/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bosima/Swift/a5978f40c3db39c9970fc05dcb6656d0ebbc4fb1/Swift.Management/wwwroot/lib/bootstrap-fileinput/img/loading.gif -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/js/locales/zh-TW.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * FileInput Chinese Traditional Translations 3 | * 4 | * This file must be loaded after 'fileinput.js'. Patterns in braces '{}', or 5 | * any HTML markup tags in the messages must not be converted or translated. 6 | * 7 | * @see http://github.com/kartik-v/bootstrap-fileinput 8 | * @author kangqf 9 | * 10 | * NOTE: this file must be saved in UTF-8 encoding. 11 | */ 12 | (function ($) { 13 | "use strict"; 14 | 15 | $.fn.fileinputLocales['zh-TW'] = { 16 | fileSingle: '單一檔案', 17 | filePlural: '複選檔案', 18 | browseLabel: '瀏覽 …', 19 | removeLabel: '移除', 20 | removeTitle: '清除選取檔案', 21 | cancelLabel: '取消', 22 | cancelTitle: '取消上傳中檔案', 23 | uploadLabel: '上傳', 24 | uploadTitle: '上傳選取檔案', 25 | msgNo: '沒有', 26 | msgNoFilesSelected: '未選擇檔案', 27 | msgCancelled: '取消', 28 | zoomTitle: '詳細資料', 29 | msgPlaceholder: '選擇 {files}...', 30 | msgZoomModalHeading: '內容預覽', 31 | msgFileRequired: '必須選擇壹個文件上傳.', 32 | msgSizeTooSmall: '檔案 "{name}" ({size} KB) 必須大於限定大小 {minSize} KB.', 33 | msgSizeTooLarge: '檔案 "{name}" ({size} KB) 大小超過上限 {maxSize} KB.', 34 | msgFilesTooLess: '最少必須選擇 {n} {files} 來上傳. ', 35 | msgFilesTooMany: '上傳的檔案數量 ({n}) 超過最大檔案上傳限制 {m}.', 36 | msgFileNotFound: '檔案 "{name}" 未發現!', 37 | msgFileSecured: '安全限制,禁止讀取檔案 "{name}".', 38 | msgFileNotReadable: '文件 "{name}" 不可讀取.', 39 | msgFilePreviewAborted: '檔案 "{name}" 預覽中止.', 40 | msgFilePreviewError: '讀取 "{name}" 發生錯誤.', 41 | msgInvalidFileName: '附檔名 "{name}" 包含非法字符.', 42 | msgInvalidFileType: '檔案類型錯誤 "{name}". 只能使用 "{types}" 類型的檔案.', 43 | msgInvalidFileExtension: '附檔名錯誤 "{name}". 只能使用 "{extensions}" 的檔案.', 44 | msgFileTypes: { 45 | 'image': 'image', 46 | 'html': 'HTML', 47 | 'text': 'text', 48 | 'video': 'video', 49 | 'audio': 'audio', 50 | 'flash': 'flash', 51 | 'pdf': 'PDF', 52 | 'object': 'object' 53 | }, 54 | msgUploadAborted: '該文件上傳被中止', 55 | msgUploadThreshold: '處理中...', 56 | msgUploadBegin: '正在初始化...', 57 | msgUploadEnd: '完成', 58 | msgUploadEmpty: '無效的文件上傳.', 59 | msgUploadError: '上傳錯誤', 60 | msgValidationError: '驗證錯誤', 61 | msgLoading: '載入第 {index} 個檔案,共 {files} …', 62 | msgProgress: '載入第 {index} 個檔案,共 {files} - {name} - {percent}% 成功.', 63 | msgSelected: '{n} {files} 選取', 64 | msgFoldersNotAllowed: '只支援單檔拖曳! 無法使用 {n} 拖拽的資料夹.', 65 | msgImageWidthSmall: '圖檔寬度"{name}"必須至少為{size}像素(px).', 66 | msgImageHeightSmall: '圖檔高度"{name}"必須至少為{size}像素(px).', 67 | msgImageWidthLarge: '圖檔寬度"{name}"不能超過{size}像素(px).', 68 | msgImageHeightLarge: '圖檔高度"{name}"不能超過{size}像素(px).', 69 | msgImageResizeError: '無法獲取的圖像尺寸調整。', 70 | msgImageResizeException: '錯誤而調整圖像大小。
{errors}
', 71 | msgAjaxError: '{operation} 發生錯誤. 請重試!', 72 | msgAjaxProgressError: '{operation} 失敗', 73 | ajaxOperations: { 74 | deleteThumb: 'file delete', 75 | uploadThumb: 'file upload', 76 | uploadBatch: 'batch file upload', 77 | uploadExtra: 'form data upload' 78 | }, 79 | dropZoneTitle: '拖曳檔案至此 …', 80 | dropZoneClickTitle: '
(或點擊{files}按鈕選擇文件)', 81 | fileActionSettings: { 82 | removeTitle: '刪除檔案', 83 | uploadTitle: '上傳檔案', 84 | uploadRetryTitle: '重試', 85 | downloadTitle: '下載檔案', 86 | zoomTitle: '詳細資料', 87 | dragTitle: '移動 / 重置', 88 | indicatorNewTitle: '尚未上傳', 89 | indicatorSuccessTitle: '上傳成功', 90 | indicatorErrorTitle: '上傳失敗', 91 | indicatorLoadingTitle: '上傳中 ...' 92 | }, 93 | previewZoomButtonTitles: { 94 | prev: '預覽上壹個文件', 95 | next: '預覽下壹個文件', 96 | toggleheader: '縮放', 97 | fullscreen: '全屏', 98 | borderless: '無邊界模式', 99 | close: '關閉當前預覽' 100 | } 101 | }; 102 | })(window.jQuery); 103 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/js/locales/zh.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * FileInput Chinese Translations 3 | * 4 | * This file must be loaded after 'fileinput.js'. Patterns in braces '{}', or 5 | * any HTML markup tags in the messages must not be converted or translated. 6 | * 7 | * @see http://github.com/kartik-v/bootstrap-fileinput 8 | * @author kangqf 9 | * 10 | * NOTE: this file must be saved in UTF-8 encoding. 11 | */ 12 | (function ($) { 13 | "use strict"; 14 | 15 | $.fn.fileinputLocales['zh'] = { 16 | fileSingle: '文件', 17 | filePlural: '个文件', 18 | browseLabel: '选择 …', 19 | removeLabel: '移除', 20 | removeTitle: '清除选中文件', 21 | cancelLabel: '取消', 22 | cancelTitle: '取消进行中的上传', 23 | uploadLabel: '上传', 24 | uploadTitle: '上传选中文件', 25 | msgNo: '没有', 26 | msgNoFilesSelected: '未选择文件', 27 | msgCancelled: '取消', 28 | msgPlaceholder: '选择 {files}...', 29 | msgZoomModalHeading: '详细预览', 30 | msgFileRequired: '必须选择一个文件上传.', 31 | msgSizeTooSmall: '文件 "{name}" ({size} KB) 必须大于限定大小 {minSize} KB.', 32 | msgSizeTooLarge: '文件 "{name}" ({size} KB) 超过了允许大小 {maxSize} KB.', 33 | msgFilesTooLess: '你必须选择最少 {n} {files} 来上传. ', 34 | msgFilesTooMany: '选择的上传文件个数 ({n}) 超出最大文件的限制个数 {m}.', 35 | msgFileNotFound: '文件 "{name}" 未找到!', 36 | msgFileSecured: '安全限制,为了防止读取文件 "{name}".', 37 | msgFileNotReadable: '文件 "{name}" 不可读.', 38 | msgFilePreviewAborted: '取消 "{name}" 的预览.', 39 | msgFilePreviewError: '读取 "{name}" 时出现了一个错误.', 40 | msgInvalidFileName: '文件名 "{name}" 包含非法字符.', 41 | msgInvalidFileType: '不正确的类型 "{name}". 只支持 "{types}" 类型的文件.', 42 | msgInvalidFileExtension: '不正确的文件扩展名 "{name}". 只支持 "{extensions}" 的文件扩展名.', 43 | msgFileTypes: { 44 | 'image': 'image', 45 | 'html': 'HTML', 46 | 'text': 'text', 47 | 'video': 'video', 48 | 'audio': 'audio', 49 | 'flash': 'flash', 50 | 'pdf': 'PDF', 51 | 'object': 'object' 52 | }, 53 | msgUploadAborted: '该文件上传被中止', 54 | msgUploadThreshold: '处理中...', 55 | msgUploadBegin: '正在初始化...', 56 | msgUploadEnd: '完成', 57 | msgUploadEmpty: '无效的文件上传.', 58 | msgUploadError: '上传出错', 59 | msgValidationError: '验证错误', 60 | msgLoading: '加载第 {index} 文件 共 {files} …', 61 | msgProgress: '加载第 {index} 文件 共 {files} - {name} - {percent}% 完成.', 62 | msgSelected: '{n} {files} 选中', 63 | msgFoldersNotAllowed: '只支持拖拽文件! 跳过 {n} 拖拽的文件夹.', 64 | msgImageWidthSmall: '图像文件的"{name}"的宽度必须是至少{size}像素.', 65 | msgImageHeightSmall: '图像文件的"{name}"的高度必须至少为{size}像素.', 66 | msgImageWidthLarge: '图像文件"{name}"的宽度不能超过{size}像素.', 67 | msgImageHeightLarge: '图像文件"{name}"的高度不能超过{size}像素.', 68 | msgImageResizeError: '无法获取的图像尺寸调整。', 69 | msgImageResizeException: '调整图像大小时发生错误。
{errors}
', 70 | msgAjaxError: '{operation} 发生错误. 请重试!', 71 | msgAjaxProgressError: '{operation} 失败', 72 | ajaxOperations: { 73 | deleteThumb: '删除文件', 74 | uploadThumb: '上传文件', 75 | uploadBatch: '批量上传', 76 | uploadExtra: '表单数据上传' 77 | }, 78 | dropZoneTitle: '拖拽文件到这里 …
支持多文件同时上传', 79 | dropZoneClickTitle: '
(或点击{files}按钮选择文件)', 80 | fileActionSettings: { 81 | removeTitle: '删除文件', 82 | uploadTitle: '上传文件', 83 | downloadTitle: '下载文件', 84 | uploadRetryTitle: '重试', 85 | zoomTitle: '查看详情', 86 | dragTitle: '移动 / 重置', 87 | indicatorNewTitle: '没有上传', 88 | indicatorSuccessTitle: '上传', 89 | indicatorErrorTitle: '上传错误', 90 | indicatorLoadingTitle: '上传 ...' 91 | }, 92 | previewZoomButtonTitles: { 93 | prev: '预览上一个文件', 94 | next: '预览下一个文件', 95 | toggleheader: '缩放', 96 | fullscreen: '全屏', 97 | borderless: '无边界模式', 98 | close: '关闭当前预览' 99 | } 100 | }; 101 | })(window.jQuery); 102 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bootstrap-fileinput", 3 | "version": "4.5.2", 4 | "homepage": "https://github.com/kartik-v/bootstrap-fileinput", 5 | "authors": [ 6 | "Kartik Visweswaran " 7 | ], 8 | "description": "An enhanced HTML 5 file input for Bootstrap 3.x with file preview, multiple selection, ajax uploads, and more features.", 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/kartik-v/bootstrap-fileinput.git" 12 | }, 13 | "bugs": { 14 | "url": "https://github.com/kartik-v/bootstrap-fileinput/issues" 15 | }, 16 | "keywords": [ 17 | "file", 18 | "input", 19 | "preview", 20 | "image", 21 | "upload", 22 | "ajax", 23 | "multiple", 24 | "delete", 25 | "progress", 26 | "gallery" 27 | ], 28 | "dependencies": { 29 | "jquery": ">= 1.9.0", 30 | "bootstrap": ">= 3.0.0" 31 | }, 32 | "main": "./js/fileinput.js", 33 | "style": "./css/fileinput.css", 34 | "peerDependencies": { 35 | "jquery": ">= 1.9.0", 36 | "bootstrap": ">= 3.0.0" 37 | }, 38 | "license": "BSD-3-Clause" 39 | } 40 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/scss/fileinput-rtl.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * bootstrap-fileinput v4.5.2 3 | * http://plugins.krajee.com/file-input 4 | * 5 | * Krajee RTL (Right To Left) default styling for bootstrap-fileinput. 6 | * 7 | * Author: Kartik Visweswaran 8 | * Copyright: 2014 - 2018, Kartik Visweswaran, Krajee.com 9 | * 10 | * Licensed under the BSD 3-Clause 11 | * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md 12 | */ 13 | 14 | //colors 15 | $zorba: #a2958a !default; 16 | $mine-shaft: #333 !default; 17 | 18 | //standard measures 19 | $radius: 4px !default; 20 | $pad: 5px !default; 21 | $border: 1px !default; 22 | 23 | //operations 24 | @function multiply($pixels, $multiplier) { 25 | @return $pixels * $multiplier; 26 | } 27 | 28 | //@extend-elements 29 | %set_float_left { 30 | float: left; 31 | } 32 | 33 | %set_float_right { 34 | float: right; 35 | } 36 | 37 | %set_text_right { 38 | text-align: right; 39 | } 40 | 41 | .kv-rtl { 42 | direction: rtl; 43 | .floating-buttons { 44 | left: multiply($pad, 2); 45 | right: auto; 46 | .btn-kv { 47 | margin-left: 0; 48 | margin-right: multiply($pad, 0.6); 49 | } 50 | } 51 | .file-caption-icon { 52 | left: auto; 53 | right: multiply($pad, 1.6); 54 | } 55 | .close { 56 | @extend %set_float_left; 57 | } 58 | .file-zoom-dialog { 59 | @extend %set_text_right; 60 | } 61 | .file-error-message { 62 | pre { 63 | @extend %set_text_right; 64 | } 65 | ul { 66 | @extend %set_text_right; 67 | } 68 | } 69 | .file-drop-zone { 70 | margin: multiply($pad, 2.4) multiply($pad, 2.4) multiply($pad, 2.4) multiply($pad, 3); 71 | } 72 | .btn-prev { 73 | right: multiply($pad, 0.2); 74 | left: auto; 75 | } 76 | .btn-next { 77 | left: multiply($pad, 0.2); 78 | right: auto; 79 | } 80 | .pull-right { 81 | float: left !important; 82 | } 83 | .pull-left { 84 | float: right !important; 85 | } 86 | .float-right { 87 | @extend .pull-right; 88 | } 89 | .float-left { 90 | @extend .pull-left; 91 | } 92 | .kv-zoom-title { 93 | direction: ltr; 94 | } 95 | .krajee-default { 96 | &.file-preview-frame { 97 | @extend %set_float_right; 98 | box-shadow: (-$border) $border multiply($border, 5) 0 $zorba; 99 | &:not(.file-preview-error):hover { 100 | box-shadow: multiply($border, -3) multiply($border, 3) multiply($border, 5) 0 $mine-shaft; 101 | } 102 | } 103 | .file-actions { 104 | @extend %set_float_left; 105 | } 106 | .file-other-error { 107 | @extend %set_float_left; 108 | } 109 | .file-drag-handle { 110 | @extend %set_float_right; 111 | } 112 | .file-upload-indicator { 113 | @extend %set_float_right; 114 | } 115 | } 116 | .kv-zoom-actions .btn-kv { 117 | margin-left: 0; 118 | margin-right: multiply($pad, 0.6); 119 | } 120 | .file-caption.icon-visible .file-caption-name { 121 | padding-left: 0; 122 | padding-right: multiply($pad, 3); 123 | } 124 | .input-group-btn > .btn:last-child { 125 | border-radius: $radius 0 0 $radius; 126 | } 127 | .input-group .form-control:first-child { 128 | border-radius: 0 $radius $radius 0; 129 | } 130 | .btn-file input[type=file] { 131 | left: auto; 132 | right: 0; 133 | text-align: left; 134 | background: none repeat scroll 100% 0 transparent; 135 | } 136 | } -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/themes/explorer-fa/theme.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * bootstrap-fileinput v4.5.2 3 | * http://plugins.krajee.com/file-input 4 | * 5 | * Krajee Explorer Font Awesome 4.x theme style for bootstrap-fileinput. Load this theme file after loading 6 | * font awesome 4.x CSS and `fileinput.css`. 7 | * 8 | * Author: Kartik Visweswaran 9 | * Copyright: 2014 - 2018, Kartik Visweswaran, Krajee.com 10 | * 11 | * Licensed under the BSD 3-Clause 12 | * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md 13 | */ 14 | .theme-explorer-fa .file-upload-indicator, .theme-explorer-fa .file-drag-handle, .theme-explorer-fa .explorer-frame .kv-file-content, .theme-explorer-fa .file-actions, .explorer-frame .file-preview-other { 15 | text-align: center; 16 | } 17 | 18 | .theme-explorer-fa .file-thumb-progress .progress, .theme-explorer-fa .file-thumb-progress .progress-bar { 19 | height: 13px; 20 | font-size: 11px; 21 | line-height: 13px; 22 | } 23 | 24 | .theme-explorer-fa .file-upload-indicator, .theme-explorer-fa .file-drag-handle { 25 | position: absolute; 26 | display: inline-block; 27 | top: 0; 28 | right: 3px; 29 | width: 16px; 30 | height: 16px; 31 | font-size: 16px; 32 | } 33 | 34 | .theme-explorer-fa .file-thumb-progress .progress, .theme-explorer-fa .explorer-caption { 35 | display: block; 36 | } 37 | 38 | .theme-explorer-fa .explorer-frame td { 39 | vertical-align: middle; 40 | text-align: left; 41 | } 42 | 43 | .theme-explorer-fa .explorer-frame .kv-file-content { 44 | width: 80px; 45 | height: 80px; 46 | padding: 5px; 47 | } 48 | 49 | .theme-explorer-fa .file-actions-cell { 50 | position: relative; 51 | width: 120px; 52 | padding: 0; 53 | } 54 | 55 | .theme-explorer-fa .file-thumb-progress .progress { 56 | margin-top: 5px; 57 | } 58 | 59 | .theme-explorer-fa .explorer-caption { 60 | color: #777; 61 | } 62 | 63 | .theme-explorer-fa .kvsortable-ghost { 64 | opacity: 0.6; 65 | background: #e1edf7; 66 | border: 2px solid #a1abff; 67 | } 68 | 69 | .theme-explorer-fa .file-preview .table { 70 | margin: 0; 71 | } 72 | 73 | .theme-explorer-fa .file-error-message ul { 74 | padding: 5px 0 0 20px; 75 | } 76 | 77 | .explorer-frame .file-preview-text { 78 | display: inline-block; 79 | color: #428bca; 80 | border: 1px solid #ddd; 81 | font-family: Menlo, Monaco, Consolas, "Courier New", monospace; 82 | outline: none; 83 | padding: 8px; 84 | resize: none; 85 | } 86 | 87 | .explorer-frame .file-preview-html { 88 | display: inline-block; 89 | border: 1px solid #ddd; 90 | padding: 8px; 91 | overflow: auto; 92 | } 93 | 94 | .explorer-frame .file-other-icon { 95 | font-size: 2.6em; 96 | } 97 | 98 | @media only screen and (max-width: 767px) { 99 | .theme-explorer-fa .table, .theme-explorer-fa .table tbody, .theme-explorer-fa .table tr, .theme-explorer-fa .table td { 100 | display: block; 101 | width: 100% !important; 102 | } 103 | 104 | .theme-explorer-fa .table { 105 | border: none; 106 | } 107 | 108 | .theme-explorer-fa .table tr { 109 | margin-top: 5px; 110 | } 111 | 112 | .theme-explorer-fa .table tr:first-child { 113 | margin-top: 0; 114 | } 115 | 116 | .theme-explorer-fa .table td { 117 | text-align: center; 118 | } 119 | 120 | .theme-explorer-fa .table .kv-file-content { 121 | border-bottom: none; 122 | padding: 4px; 123 | margin: 0; 124 | } 125 | 126 | .theme-explorer-fa .table .kv-file-content .file-preview-image { 127 | max-width: 100%; 128 | font-size: 20px; 129 | } 130 | 131 | .theme-explorer-fa .file-details-cell { 132 | border-top: none; 133 | border-bottom: none; 134 | padding-top: 0; 135 | margin: 0; 136 | } 137 | 138 | .theme-explorer-fa .file-actions-cell { 139 | border-top: none; 140 | padding-bottom: 4px; 141 | } 142 | 143 | .theme-explorer-fa .explorer-frame .explorer-caption { 144 | white-space: nowrap; 145 | text-overflow: ellipsis; 146 | overflow: hidden; 147 | left: 0; 148 | right: 0; 149 | margin: auto; 150 | } 151 | } 152 | 153 | /*noinspection CssOverwrittenProperties*/ 154 | .file-zoom-dialog .explorer-frame .file-other-icon { 155 | font-size: 22em; 156 | font-size: 50vmin; 157 | } -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/themes/explorer-fa/theme.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * bootstrap-fileinput v4.5.2 3 | * http://plugins.krajee.com/file-input 4 | * 5 | * Krajee Explorer Font Awesome 4.x theme style for bootstrap-fileinput. Load this theme file after loading 6 | * font awesome 4.x CSS and `fileinput.css`. 7 | * 8 | * Author: Kartik Visweswaran 9 | * Copyright: 2014 - 2018, Kartik Visweswaran, Krajee.com 10 | * 11 | * Licensed under the BSD 3-Clause 12 | * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md 13 | */.explorer-frame .file-preview-other,.theme-explorer-fa .explorer-frame .kv-file-content,.theme-explorer-fa .file-actions,.theme-explorer-fa .file-drag-handle,.theme-explorer-fa .file-upload-indicator{text-align:center}.theme-explorer-fa .file-thumb-progress .progress,.theme-explorer-fa .file-thumb-progress .progress-bar{height:13px;font-size:11px;line-height:13px}.theme-explorer-fa .file-drag-handle,.theme-explorer-fa .file-upload-indicator{position:absolute;display:inline-block;top:0;right:3px;width:16px;height:16px;font-size:16px}.theme-explorer-fa .explorer-caption,.theme-explorer-fa .file-thumb-progress .progress{display:block}.theme-explorer-fa .explorer-frame td{vertical-align:middle;text-align:left}.theme-explorer-fa .explorer-frame .kv-file-content{width:80px;height:80px;padding:5px}.theme-explorer-fa .file-actions-cell{position:relative;width:120px;padding:0}.theme-explorer-fa .file-thumb-progress .progress{margin-top:5px}.theme-explorer-fa .explorer-caption{color:#777}.theme-explorer-fa .kvsortable-ghost{opacity:.6;background:#e1edf7;border:2px solid #a1abff}.theme-explorer-fa .file-preview .table{margin:0}.theme-explorer-fa .file-error-message ul{padding:5px 0 0 20px}.explorer-frame .file-preview-text{display:inline-block;color:#428bca;border:1px solid #ddd;font-family:Menlo,Monaco,Consolas,"Courier New",monospace;outline:0;padding:8px;resize:none}.explorer-frame .file-preview-html{display:inline-block;border:1px solid #ddd;padding:8px;overflow:auto}.explorer-frame .file-other-icon{font-size:2.6em}@media only screen and (max-width:767px){.theme-explorer-fa .table,.theme-explorer-fa .table tbody,.theme-explorer-fa .table td,.theme-explorer-fa .table tr{display:block;width:100%!important}.theme-explorer-fa .table{border:none}.theme-explorer-fa .table tr{margin-top:5px}.theme-explorer-fa .table tr:first-child{margin-top:0}.theme-explorer-fa .table td{text-align:center}.theme-explorer-fa .table .kv-file-content{border-bottom:none;padding:4px;margin:0}.theme-explorer-fa .table .kv-file-content .file-preview-image{max-width:100%;font-size:20px}.theme-explorer-fa .file-details-cell{border-top:none;border-bottom:none;padding-top:0;margin:0}.theme-explorer-fa .file-actions-cell{border-top:none;padding-bottom:4px}.theme-explorer-fa .explorer-frame .explorer-caption{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;left:0;right:0;margin:auto}}.file-zoom-dialog .explorer-frame .file-other-icon{font-size:22em;font-size:50vmin} -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/themes/explorer-fa/theme.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * bootstrap-fileinput v4.5.2 3 | * http://plugins.krajee.com/file-input 4 | * 5 | * Krajee Explorer Font Awesome theme configuration for bootstrap-fileinput. 6 | * Load this theme file after loading `fileinput.js`. Ensure that 7 | * font awesome assets and CSS are loaded on the page as well. 8 | * 9 | * Author: Kartik Visweswaran 10 | * Copyright: 2014 - 2018, Kartik Visweswaran, Krajee.com 11 | * 12 | * Licensed under the BSD 3-Clause 13 | * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md 14 | */!function(a){"use strict";var e='\n {close}
\n \n
\n
\n
\n
\n',footer:'
{caption}
{size}{progress}{indicator} {actions}',actions:'{drag}\n
\n \n
',zoomCache:'{zoomContent}
',fileIcon:' '},previewMarkupTags:{tagBefore1:e+">"+i,tagBefore2:e+' title="{caption}">'+i,tagAfter:"\n{footer}\n"},previewSettings:{image:{height:"60px"},html:{width:"100px",height:"60px"},text:{width:"100px",height:"60px"},video:{width:"auto",height:"60px"},audio:{width:"auto",height:"60px"},flash:{width:"100%",height:"60px"},object:{width:"100%",height:"60px"},pdf:{width:"100px",height:"60px"},other:{width:"100%",height:"60px"}},frameClass:"explorer-frame",fileActionSettings:{removeIcon:'',uploadIcon:'',uploadRetryIcon:'',downloadIcon:'',zoomIcon:'',dragIcon:'',indicatorNew:'',indicatorSuccess:'',indicatorError:'',indicatorLoading:''},previewZoomButtonIcons:{prev:'',next:'',toggleheader:'',fullscreen:'',borderless:'',close:''},previewFileIcon:'',browseIcon:'',removeIcon:'',cancelIcon:'',uploadIcon:'',msgValidationErrorIcon:' '}}(window.jQuery); -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/themes/explorer-fas/theme.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * bootstrap-fileinput v4.5.2 3 | * http://plugins.krajee.com/file-input 4 | * 5 | * Krajee Explorer Font Awesome 5.x theme style for bootstrap-fileinput. Load this theme file after loading 6 | * font awesome 5.x CSS and `fileinput.css`. 7 | * 8 | * Author: Kartik Visweswaran 9 | * Copyright: 2014 - 2018, Kartik Visweswaran, Krajee.com 10 | * 11 | * Licensed under the BSD 3-Clause 12 | * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md 13 | */ 14 | .theme-explorer-fas .file-upload-indicator, .theme-explorer-fas .file-drag-handle, .theme-explorer-fas .explorer-frame .kv-file-content, .theme-explorer-fas .file-actions, .explorer-frame .file-preview-other { 15 | text-align: center; 16 | } 17 | 18 | .theme-explorer-fas .file-thumb-progress .progress, .theme-explorer-fas .file-thumb-progress .progress-bar { 19 | height: 13px; 20 | font-size: 11px; 21 | line-height: 13px; 22 | } 23 | 24 | .theme-explorer-fas .file-upload-indicator, .theme-explorer-fas .file-drag-handle { 25 | position: absolute; 26 | display: inline-block; 27 | top: 0; 28 | right: 3px; 29 | width: 16px; 30 | height: 16px; 31 | font-size: 16px; 32 | } 33 | 34 | .theme-explorer-fas .file-thumb-progress .progress, .theme-explorer-fas .explorer-caption { 35 | display: block; 36 | } 37 | 38 | .theme-explorer-fas .explorer-frame td { 39 | vertical-align: middle; 40 | text-align: left; 41 | } 42 | 43 | .theme-explorer-fas .explorer-frame .kv-file-content { 44 | width: 80px; 45 | height: 80px; 46 | padding: 5px; 47 | } 48 | 49 | .theme-explorer-fas .file-actions-cell { 50 | position: relative; 51 | width: 120px; 52 | padding: 0; 53 | } 54 | 55 | .theme-explorer-fas .file-thumb-progress .progress { 56 | margin-top: 5px; 57 | } 58 | 59 | .theme-explorer-fas .explorer-caption { 60 | color: #777; 61 | } 62 | 63 | .theme-explorer-fas .kvsortable-ghost { 64 | opacity: 0.6; 65 | background: #e1edf7; 66 | border: 2px solid #a1abff; 67 | } 68 | 69 | .theme-explorer-fas .file-preview .table { 70 | margin: 0; 71 | } 72 | 73 | .theme-explorer-fas .file-error-message ul { 74 | padding: 5px 0 0 20px; 75 | } 76 | 77 | .explorer-frame .file-preview-text { 78 | display: inline-block; 79 | color: #428bca; 80 | border: 1px solid #ddd; 81 | font-family: Menlo, Monaco, Consolas, "Courier New", monospace; 82 | outline: none; 83 | padding: 8px; 84 | resize: none; 85 | } 86 | 87 | .explorer-frame .file-preview-html { 88 | display: inline-block; 89 | border: 1px solid #ddd; 90 | padding: 8px; 91 | overflow: auto; 92 | } 93 | 94 | .explorer-frame .file-other-icon { 95 | font-size: 2.6em; 96 | } 97 | 98 | @media only screen and (max-width: 767px) { 99 | .theme-explorer-fas .table, .theme-explorer-fas .table tbody, .theme-explorer-fas .table tr, .theme-explorer-fas .table td { 100 | display: block; 101 | width: 100% !important; 102 | } 103 | 104 | .theme-explorer-fas .table { 105 | border: none; 106 | } 107 | 108 | .theme-explorer-fas .table tr { 109 | margin-top: 5px; 110 | } 111 | 112 | .theme-explorer-fas .table tr:first-child { 113 | margin-top: 0; 114 | } 115 | 116 | .theme-explorer-fas .table td { 117 | text-align: center; 118 | } 119 | 120 | .theme-explorer-fas .table .kv-file-content { 121 | border-bottom: none; 122 | padding: 4px; 123 | margin: 0; 124 | } 125 | 126 | .theme-explorer-fas .table .kv-file-content .file-preview-image { 127 | max-width: 100%; 128 | font-size: 20px; 129 | } 130 | 131 | .theme-explorer-fas .file-details-cell { 132 | border-top: none; 133 | border-bottom: none; 134 | padding-top: 0; 135 | margin: 0; 136 | } 137 | 138 | .theme-explorer-fas .file-actions-cell { 139 | border-top: none; 140 | padding-bottom: 4px; 141 | } 142 | 143 | .theme-explorer-fas .explorer-frame .explorer-caption { 144 | white-space: nowrap; 145 | text-overflow: ellipsis; 146 | overflow: hidden; 147 | left: 0; 148 | right: 0; 149 | margin: auto; 150 | } 151 | } 152 | 153 | /*noinspection CssOverwrittenProperties*/ 154 | .file-zoom-dialog .explorer-frame .file-other-icon { 155 | font-size: 22em; 156 | font-size: 50vmin; 157 | } -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/themes/explorer-fas/theme.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * bootstrap-fileinput v4.5.2 3 | * http://plugins.krajee.com/file-input 4 | * 5 | * Krajee Explorer Font Awesome 5.x theme style for bootstrap-fileinput. Load this theme file after loading 6 | * font awesome 5.x CSS and `fileinput.css`. 7 | * 8 | * Author: Kartik Visweswaran 9 | * Copyright: 2014 - 2018, Kartik Visweswaran, Krajee.com 10 | * 11 | * Licensed under the BSD 3-Clause 12 | * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md 13 | */.explorer-frame .file-preview-other,.theme-explorer-fas .explorer-frame .kv-file-content,.theme-explorer-fas .file-actions,.theme-explorer-fas .file-drag-handle,.theme-explorer-fas .file-upload-indicator{text-align:center}.theme-explorer-fas .file-thumb-progress .progress,.theme-explorer-fas .file-thumb-progress .progress-bar{height:13px;font-size:11px;line-height:13px}.theme-explorer-fas .file-drag-handle,.theme-explorer-fas .file-upload-indicator{position:absolute;display:inline-block;top:0;right:3px;width:16px;height:16px;font-size:16px}.theme-explorer-fas .explorer-caption,.theme-explorer-fas .file-thumb-progress .progress{display:block}.theme-explorer-fas .explorer-frame td{vertical-align:middle;text-align:left}.theme-explorer-fas .explorer-frame .kv-file-content{width:80px;height:80px;padding:5px}.theme-explorer-fas .file-actions-cell{position:relative;width:120px;padding:0}.theme-explorer-fas .file-thumb-progress .progress{margin-top:5px}.theme-explorer-fas .explorer-caption{color:#777}.theme-explorer-fas .kvsortable-ghost{opacity:.6;background:#e1edf7;border:2px solid #a1abff}.theme-explorer-fas .file-preview .table{margin:0}.theme-explorer-fas .file-error-message ul{padding:5px 0 0 20px}.explorer-frame .file-preview-text{display:inline-block;color:#428bca;border:1px solid #ddd;font-family:Menlo,Monaco,Consolas,"Courier New",monospace;outline:0;padding:8px;resize:none}.explorer-frame .file-preview-html{display:inline-block;border:1px solid #ddd;padding:8px;overflow:auto}.explorer-frame .file-other-icon{font-size:2.6em}@media only screen and (max-width:767px){.theme-explorer-fas .table,.theme-explorer-fas .table tbody,.theme-explorer-fas .table td,.theme-explorer-fas .table tr{display:block;width:100%!important}.theme-explorer-fas .table{border:none}.theme-explorer-fas .table tr{margin-top:5px}.theme-explorer-fas .table tr:first-child{margin-top:0}.theme-explorer-fas .table td{text-align:center}.theme-explorer-fas .table .kv-file-content{border-bottom:none;padding:4px;margin:0}.theme-explorer-fas .table .kv-file-content .file-preview-image{max-width:100%;font-size:20px}.theme-explorer-fas .file-details-cell{border-top:none;border-bottom:none;padding-top:0;margin:0}.theme-explorer-fas .file-actions-cell{border-top:none;padding-bottom:4px}.theme-explorer-fas .explorer-frame .explorer-caption{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;left:0;right:0;margin:auto}}.file-zoom-dialog .explorer-frame .file-other-icon{font-size:22em;font-size:50vmin} -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/themes/explorer-fas/theme.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * bootstrap-fileinput v4.5.2 3 | * http://plugins.krajee.com/file-input 4 | * 5 | * Krajee Explorer Font Awesome theme configuration for bootstrap-fileinput. 6 | * Load this theme file after loading `fileinput.js`. Ensure that 7 | * font awesome assets and CSS are loaded on the page as well. 8 | * 9 | * Author: Kartik Visweswaran 10 | * Copyright: 2014 - 2018, Kartik Visweswaran, Krajee.com 11 | * 12 | * Licensed under the BSD 3-Clause 13 | * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md 14 | */!function(a){"use strict";var e='\n {close}
\n \n
\n
\n
\n
\n',footer:'
{caption}
{size}{progress}{indicator} {actions}',actions:'{drag}\n
\n \n
',zoomCache:'{zoomContent}
',fileIcon:' '},previewMarkupTags:{tagBefore1:e+">"+i,tagBefore2:e+' title="{caption}">'+i,tagAfter:"\n{footer}\n"},previewSettings:{image:{height:"60px"},html:{width:"100px",height:"60px"},text:{width:"100px",height:"60px"},video:{width:"auto",height:"60px"},audio:{width:"auto",height:"60px"},flash:{width:"100%",height:"60px"},object:{width:"100%",height:"60px"},pdf:{width:"100px",height:"60px"},other:{width:"100%",height:"60px"}},frameClass:"explorer-frame",fileActionSettings:{removeIcon:'',uploadIcon:'',uploadRetryIcon:'',downloadIcon:'',zoomIcon:'',dragIcon:'',indicatorNew:'',indicatorSuccess:'',indicatorError:'',indicatorLoading:''},previewZoomButtonIcons:{prev:'',next:'',toggleheader:'',fullscreen:'',borderless:'',close:''},previewFileIcon:'',browseIcon:'',removeIcon:'',cancelIcon:'',uploadIcon:'',msgValidationErrorIcon:' '}}(window.jQuery); -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/themes/explorer/theme.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * bootstrap-fileinput v4.5.2 3 | * http://plugins.krajee.com/file-input 4 | * 5 | * Krajee Explorer theme style for bootstrap-fileinput. Load this theme file after loading `fileinput.css`. 6 | * 7 | * Author: Kartik Visweswaran 8 | * Copyright: 2014 - 2018, Kartik Visweswaran, Krajee.com 9 | * 10 | * Licensed under the BSD 3-Clause 11 | * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md 12 | */ 13 | .theme-explorer .file-upload-indicator, .theme-explorer .file-drag-handle, .theme-explorer .explorer-frame .kv-file-content, .theme-explorer .file-actions, .explorer-frame .file-preview-other { 14 | text-align: center; 15 | } 16 | 17 | .theme-explorer .file-thumb-progress .progress, .theme-explorer .file-thumb-progress .progress-bar { 18 | height: 13px; 19 | font-size: 11px; 20 | line-height: 13px; 21 | } 22 | 23 | .theme-explorer .file-upload-indicator, .theme-explorer .file-drag-handle { 24 | position: absolute; 25 | display: inline-block; 26 | top: 0; 27 | right: 3px; 28 | width: 16px; 29 | height: 16px; 30 | font-size: 16px; 31 | } 32 | 33 | .theme-explorer .file-thumb-progress .progress, .theme-explorer .explorer-caption { 34 | display: block; 35 | } 36 | 37 | .theme-explorer .explorer-frame td { 38 | vertical-align: middle; 39 | text-align: left; 40 | } 41 | 42 | .theme-explorer .explorer-frame .kv-file-content { 43 | width: 80px; 44 | height: 80px; 45 | padding: 5px; 46 | } 47 | 48 | .theme-explorer .file-actions-cell { 49 | position: relative; 50 | width: 120px; 51 | padding: 0; 52 | } 53 | 54 | .theme-explorer .file-thumb-progress .progress { 55 | margin-top: 5px; 56 | } 57 | 58 | .theme-explorer .explorer-caption { 59 | color: #777; 60 | } 61 | 62 | .theme-explorer .kvsortable-ghost { 63 | opacity: 0.6; 64 | background: #e1edf7; 65 | border: 2px solid #a1abff; 66 | } 67 | 68 | .theme-explorer .file-preview .table { 69 | margin: 0; 70 | } 71 | 72 | .theme-explorer .file-error-message ul { 73 | padding: 5px 0 0 20px; 74 | } 75 | 76 | .explorer-frame .file-preview-text { 77 | display: inline-block; 78 | color: #428bca; 79 | border: 1px solid #ddd; 80 | font-family: Menlo, Monaco, Consolas, "Courier New", monospace; 81 | outline: none; 82 | padding: 8px; 83 | resize: none; 84 | } 85 | 86 | .explorer-frame .file-preview-html { 87 | display: inline-block; 88 | border: 1px solid #ddd; 89 | padding: 8px; 90 | overflow: auto; 91 | } 92 | 93 | .explorer-frame .file-other-icon { 94 | font-size: 2.6em; 95 | } 96 | 97 | @media only screen and (max-width: 767px) { 98 | .theme-explorer .table, .theme-explorer .table tbody, .theme-explorer .table tr, .theme-explorer .table td { 99 | display: block; 100 | width: 100% !important; 101 | } 102 | 103 | .theme-explorer .table { 104 | border: none; 105 | } 106 | 107 | .theme-explorer .table tr { 108 | margin-top: 5px; 109 | } 110 | 111 | .theme-explorer .table tr:first-child { 112 | margin-top: 0; 113 | } 114 | 115 | .theme-explorer .table td { 116 | text-align: center; 117 | } 118 | 119 | .theme-explorer .table .kv-file-content { 120 | border-bottom: none; 121 | padding: 4px; 122 | margin: 0; 123 | } 124 | 125 | .theme-explorer .table .kv-file-content .file-preview-image { 126 | max-width: 100%; 127 | font-size: 20px; 128 | } 129 | 130 | .theme-explorer .file-details-cell { 131 | border-top: none; 132 | border-bottom: none; 133 | padding-top: 0; 134 | margin: 0; 135 | } 136 | 137 | .theme-explorer .file-actions-cell { 138 | border-top: none; 139 | padding-bottom: 4px; 140 | } 141 | 142 | .theme-explorer .explorer-frame .explorer-caption { 143 | white-space: nowrap; 144 | text-overflow: ellipsis; 145 | overflow: hidden; 146 | left: 0; 147 | right: 0; 148 | margin: auto; 149 | } 150 | } 151 | 152 | /*noinspection CssOverwrittenProperties*/ 153 | .file-zoom-dialog .explorer-frame .file-other-icon { 154 | font-size: 22em; 155 | font-size: 50vmin; 156 | } 157 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/themes/explorer/theme.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * bootstrap-fileinput v4.5.2 3 | * http://plugins.krajee.com/file-input 4 | * 5 | * Krajee Explorer theme configuration for bootstrap-fileinput. Load this theme file after loading `fileinput.js`. 6 | * 7 | * Author: Kartik Visweswaran 8 | * Copyright: 2014 - 2018, Kartik Visweswaran, Krajee.com 9 | * 10 | * Licensed under the BSD 3-Clause 11 | * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md 12 | */ 13 | (function ($) { 14 | "use strict"; 15 | var teTagBef = '\n' + 20 | ' {close}' + 21 | '
\n' + 22 | ' \n' + 23 | '
\n' + 24 | '
' + 25 | '
\n' + 26 | '
\n' + 27 | '
\n' + 28 | '', 29 | footer: '
{caption}
' + 30 | '{size}{progress}{indicator} {actions}', 31 | actions: '{drag}\n' + 32 | '
\n' + 33 | ' \n' + 36 | '
', 37 | zoomCache: '' + 38 | '{zoomContent}
' 39 | }, 40 | previewMarkupTags: { 41 | tagBefore1: teTagBef + '>' + teContent, 42 | tagBefore2: teTagBef + ' title="{caption}">' + teContent, 43 | tagAfter: '\n{footer}\n' 44 | }, 45 | previewSettings: { 46 | image: {height: "60px"}, 47 | html: {width: "100px", height: "60px"}, 48 | text: {width: "100px", height: "60px"}, 49 | video: {width: "auto", height: "60px"}, 50 | audio: {width: "auto", height: "60px"}, 51 | flash: {width: "100%", height: "60px"}, 52 | object: {width: "100%", height: "60px"}, 53 | pdf: {width: "100px", height: "60px"}, 54 | other: {width: "100%", height: "60px"} 55 | }, 56 | frameClass: 'explorer-frame' 57 | }; 58 | })(window.jQuery); 59 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/themes/explorer/theme.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * bootstrap-fileinput v4.5.2 3 | * http://plugins.krajee.com/file-input 4 | * 5 | * Krajee Explorer theme style for bootstrap-fileinput. Load this theme file after loading `fileinput.css`. 6 | * 7 | * Author: Kartik Visweswaran 8 | * Copyright: 2014 - 2018, Kartik Visweswaran, Krajee.com 9 | * 10 | * Licensed under the BSD 3-Clause 11 | * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md 12 | */.explorer-frame .file-preview-other,.theme-explorer .explorer-frame .kv-file-content,.theme-explorer .file-actions,.theme-explorer .file-drag-handle,.theme-explorer .file-upload-indicator{text-align:center}.theme-explorer .file-thumb-progress .progress,.theme-explorer .file-thumb-progress .progress-bar{height:13px;font-size:11px;line-height:13px}.theme-explorer .file-drag-handle,.theme-explorer .file-upload-indicator{position:absolute;display:inline-block;top:0;right:3px;width:16px;height:16px;font-size:16px}.theme-explorer .explorer-caption,.theme-explorer .file-thumb-progress .progress{display:block}.theme-explorer .explorer-frame td{vertical-align:middle;text-align:left}.theme-explorer .explorer-frame .kv-file-content{width:80px;height:80px;padding:5px}.theme-explorer .file-actions-cell{position:relative;width:120px;padding:0}.theme-explorer .file-thumb-progress .progress{margin-top:5px}.theme-explorer .explorer-caption{color:#777}.theme-explorer .kvsortable-ghost{opacity:.6;background:#e1edf7;border:2px solid #a1abff}.theme-explorer .file-preview .table{margin:0}.theme-explorer .file-error-message ul{padding:5px 0 0 20px}.explorer-frame .file-preview-text{display:inline-block;color:#428bca;border:1px solid #ddd;font-family:Menlo,Monaco,Consolas,"Courier New",monospace;outline:0;padding:8px;resize:none}.explorer-frame .file-preview-html{display:inline-block;border:1px solid #ddd;padding:8px;overflow:auto}.explorer-frame .file-other-icon{font-size:2.6em}@media only screen and (max-width:767px){.theme-explorer .table,.theme-explorer .table tbody,.theme-explorer .table td,.theme-explorer .table tr{display:block;width:100%!important}.theme-explorer .table{border:none}.theme-explorer .table tr{margin-top:5px}.theme-explorer .table tr:first-child{margin-top:0}.theme-explorer .table td{text-align:center}.theme-explorer .table .kv-file-content{border-bottom:none;padding:4px;margin:0}.theme-explorer .table .kv-file-content .file-preview-image{max-width:100%;font-size:20px}.theme-explorer .file-details-cell{border-top:none;border-bottom:none;padding-top:0;margin:0}.theme-explorer .file-actions-cell{border-top:none;padding-bottom:4px}.theme-explorer .explorer-frame .explorer-caption{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;left:0;right:0;margin:auto}}.file-zoom-dialog .explorer-frame .file-other-icon{font-size:22em;font-size:50vmin} -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/themes/explorer/theme.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * bootstrap-fileinput v4.5.2 3 | * http://plugins.krajee.com/file-input 4 | * 5 | * Krajee Explorer theme configuration for bootstrap-fileinput. Load this theme file after loading `fileinput.js`. 6 | * 7 | * Author: Kartik Visweswaran 8 | * Copyright: 2014 - 2018, Kartik Visweswaran, Krajee.com 9 | * 10 | * Licensed under the BSD 3-Clause 11 | * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md 12 | */!function(e){"use strict";var t='\n {close}
\n \n
\n
\n
\n
\n',footer:'
{caption}
{size}{progress}{indicator} {actions}',actions:'{drag}\n
\n \n
',zoomCache:'{zoomContent}
'},previewMarkupTags:{tagBefore1:t+">"+i,tagBefore2:t+' title="{caption}">'+i,tagAfter:"\n{footer}\n"},previewSettings:{image:{height:"60px"},html:{width:"100px",height:"60px"},text:{width:"100px",height:"60px"},video:{width:"auto",height:"60px"},audio:{width:"auto",height:"60px"},flash:{width:"100%",height:"60px"},object:{width:"100%",height:"60px"},pdf:{width:"100px",height:"60px"},other:{width:"100%",height:"60px"}},frameClass:"explorer-frame"}}(window.jQuery); 13 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/themes/fa/theme.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * bootstrap-fileinput v4.5.2 3 | * http://plugins.krajee.com/file-input 4 | * 5 | * Font Awesome icon theme configuration for bootstrap-fileinput. Requires font awesome assets to be loaded. 6 | * 7 | * Author: Kartik Visweswaran 8 | * Copyright: 2014 - 2018, Kartik Visweswaran, Krajee.com 9 | * 10 | * Licensed under the BSD 3-Clause 11 | * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md 12 | */ 13 | (function ($) { 14 | "use strict"; 15 | 16 | $.fn.fileinputThemes.fa = { 17 | fileActionSettings: { 18 | removeIcon: '', 19 | uploadIcon: '', 20 | uploadRetryIcon: '', 21 | downloadIcon: '', 22 | zoomIcon: '', 23 | dragIcon: '', 24 | indicatorNew: '', 25 | indicatorSuccess: '', 26 | indicatorError: '', 27 | indicatorLoading: '' 28 | }, 29 | layoutTemplates: { 30 | fileIcon: ' ' 31 | }, 32 | previewZoomButtonIcons: { 33 | prev: '', 34 | next: '', 35 | toggleheader: '', 36 | fullscreen: '', 37 | borderless: '', 38 | close: '' 39 | }, 40 | previewFileIcon: '', 41 | browseIcon: '', 42 | removeIcon: '', 43 | cancelIcon: '', 44 | uploadIcon: '', 45 | msgValidationErrorIcon: ' ' 46 | }; 47 | })(window.jQuery); 48 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/themes/fa/theme.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * bootstrap-fileinput v4.5.2 3 | * http://plugins.krajee.com/file-input 4 | * 5 | * Font Awesome icon theme configuration for bootstrap-fileinput. Requires font awesome assets to be loaded. 6 | * 7 | * Author: Kartik Visweswaran 8 | * Copyright: 2014 - 2018, Kartik Visweswaran, Krajee.com 9 | * 10 | * Licensed under the BSD 3-Clause 11 | * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md 12 | */!function(a){"use strict";a.fn.fileinputThemes.fa={fileActionSettings:{removeIcon:'',uploadIcon:'',uploadRetryIcon:'',downloadIcon:'',zoomIcon:'',dragIcon:'',indicatorNew:'',indicatorSuccess:'',indicatorError:'',indicatorLoading:''},layoutTemplates:{fileIcon:' '},previewZoomButtonIcons:{prev:'',next:'',toggleheader:'',fullscreen:'',borderless:'',close:''},previewFileIcon:'',browseIcon:'',removeIcon:'',cancelIcon:'',uploadIcon:'',msgValidationErrorIcon:' '}}(window.jQuery); -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/themes/fas/theme.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * bootstrap-fileinput v4.5.2 3 | * http://plugins.krajee.com/file-input 4 | * 5 | * Font Awesome 5 icon theme configuration for bootstrap-fileinput. Requires font awesome 5 assets to be loaded. 6 | * 7 | * Author: Kartik Visweswaran 8 | * Copyright: 2014 - 2018, Kartik Visweswaran, Krajee.com 9 | * 10 | * Licensed under the BSD 3-Clause 11 | * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md 12 | */ 13 | (function ($) { 14 | "use strict"; 15 | 16 | $.fn.fileinputThemes.fas = { 17 | fileActionSettings: { 18 | removeIcon: '', 19 | uploadIcon: '', 20 | uploadRetryIcon: '', 21 | downloadIcon: '', 22 | zoomIcon: '', 23 | dragIcon: '', 24 | indicatorNew: '', 25 | indicatorSuccess: '', 26 | indicatorError: '', 27 | indicatorLoading: '' 28 | }, 29 | layoutTemplates: { 30 | fileIcon: ' ' 31 | }, 32 | previewZoomButtonIcons: { 33 | prev: '', 34 | next: '', 35 | toggleheader: '', 36 | fullscreen: '', 37 | borderless: '', 38 | close: '' 39 | }, 40 | previewFileIcon: '', 41 | browseIcon: '', 42 | removeIcon: '', 43 | cancelIcon: '', 44 | uploadIcon: '', 45 | msgValidationErrorIcon: ' ' 46 | }; 47 | })(window.jQuery); 48 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/themes/fas/theme.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * bootstrap-fileinput v4.5.2 3 | * http://plugins.krajee.com/file-input 4 | * 5 | * Font Awesome 5 icon theme configuration for bootstrap-fileinput. Requires font awesome 5 assets to be loaded. 6 | * 7 | * Author: Kartik Visweswaran 8 | * Copyright: 2014 - 2018, Kartik Visweswaran, Krajee.com 9 | * 10 | * Licensed under the BSD 3-Clause 11 | * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md 12 | */!function(a){"use strict";a.fn.fileinputThemes.fas={fileActionSettings:{removeIcon:'',uploadIcon:'',uploadRetryIcon:'',downloadIcon:'',zoomIcon:'',dragIcon:'',indicatorNew:'',indicatorSuccess:'',indicatorError:'',indicatorLoading:''},layoutTemplates:{fileIcon:' '},previewZoomButtonIcons:{prev:'',next:'',toggleheader:'',fullscreen:'',borderless:'',close:''},previewFileIcon:'',browseIcon:'',removeIcon:'',cancelIcon:'',uploadIcon:'',msgValidationErrorIcon:' '}}(window.jQuery); 13 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/themes/gly/theme.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * bootstrap-fileinput v4.5.2 3 | * http://plugins.krajee.com/file-input 4 | * 5 | * Glyphicon (default) theme configuration for bootstrap-fileinput. 6 | * 7 | * Author: Kartik Visweswaran 8 | * Copyright: 2014 - 2018, Kartik Visweswaran, Krajee.com 9 | * 10 | * Licensed under the BSD 3-Clause 11 | * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md 12 | */ 13 | (function ($) { 14 | "use strict"; 15 | 16 | $.fn.fileinputThemes.gly = { 17 | fileActionSettings: { 18 | removeIcon: '', 19 | uploadIcon: '', 20 | zoomIcon: '', 21 | dragIcon: '', 22 | indicatorNew: '', 23 | indicatorSuccess: '', 24 | indicatorError: '', 25 | indicatorLoading: '' 26 | }, 27 | layoutTemplates: { 28 | fileIcon: '' 29 | }, 30 | previewZoomButtonIcons: { 31 | prev: '', 32 | next: '', 33 | toggleheader: '', 34 | fullscreen: '', 35 | borderless: '', 36 | close: '' 37 | }, 38 | previewFileIcon: '', 39 | browseIcon: ' ', 40 | removeIcon: '', 41 | cancelIcon: '', 42 | uploadIcon: '', 43 | msgValidationErrorIcon: ' ' 44 | }; 45 | })(window.jQuery); 46 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap-fileinput/themes/gly/theme.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * bootstrap-fileinput v4.5.2 3 | * http://plugins.krajee.com/file-input 4 | * 5 | * Glyphicon (default) theme configuration for bootstrap-fileinput. 6 | * 7 | * Author: Kartik Visweswaran 8 | * Copyright: 2014 - 2018, Kartik Visweswaran, Krajee.com 9 | * 10 | * Licensed under the BSD 3-Clause 11 | * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md 12 | */!function(i){"use strict";i.fn.fileinputThemes.gly={fileActionSettings:{removeIcon:'',uploadIcon:'',zoomIcon:'',dragIcon:'',indicatorNew:'',indicatorSuccess:'',indicatorError:'',indicatorLoading:''},layoutTemplates:{fileIcon:''},previewZoomButtonIcons:{prev:'',next:'',toggleheader:'',fullscreen:'',borderless:'',close:''},previewFileIcon:'',browseIcon:' ',removeIcon:'',cancelIcon:'',uploadIcon:'',msgValidationErrorIcon:' '}}(window.jQuery); -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bootstrap", 3 | "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.", 4 | "keywords": [ 5 | "css", 6 | "js", 7 | "less", 8 | "mobile-first", 9 | "responsive", 10 | "front-end", 11 | "framework", 12 | "web" 13 | ], 14 | "homepage": "http://getbootstrap.com", 15 | "license": "MIT", 16 | "moduleType": "globals", 17 | "main": [ 18 | "less/bootstrap.less", 19 | "dist/js/bootstrap.js" 20 | ], 21 | "ignore": [ 22 | "/.*", 23 | "_config.yml", 24 | "CNAME", 25 | "composer.json", 26 | "CONTRIBUTING.md", 27 | "docs", 28 | "js/tests", 29 | "test-infra" 30 | ], 31 | "dependencies": { 32 | "jquery": "1.9.1 - 3" 33 | }, 34 | "version": "3.4.1", 35 | "_release": "3.4.1", 36 | "_resolution": { 37 | "type": "version", 38 | "tag": "v3.4.1", 39 | "commit": "0b9c4a4007c44201dce9a6cc1a38407005c26c86" 40 | }, 41 | "_source": "https://github.com/twbs/bootstrap.git", 42 | "_target": "v3.4.1", 43 | "_originalSource": "bootstrap", 44 | "_direct": true 45 | } -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2016 Twitter, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bosima/Swift/a5978f40c3db39c9970fc05dcb6656d0ebbc4fb1/Swift.Management/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bosima/Swift/a5978f40c3db39c9970fc05dcb6656d0ebbc4fb1/Swift.Management/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bosima/Swift/a5978f40c3db39c9970fc05dcb6656d0ebbc4fb1/Swift.Management/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bosima/Swift/a5978f40c3db39c9970fc05dcb6656d0ebbc4fb1/Swift.Management/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/bootstrap/dist/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/jquery-validation-unobtrusive/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-validation-unobtrusive", 3 | "homepage": "https://github.com/aspnet/jquery-validation-unobtrusive", 4 | "version": "3.2.9", 5 | "_release": "3.2.9", 6 | "_resolution": { 7 | "type": "version", 8 | "tag": "v3.2.9", 9 | "commit": "a91f5401898e125f10771c5f5f0909d8c4c82396" 10 | }, 11 | "_source": "https://github.com/aspnet/jquery-validation-unobtrusive.git", 12 | "_target": "^3.2.9", 13 | "_originalSource": "jquery-validation-unobtrusive", 14 | "_direct": true 15 | } -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) .NET Foundation. All rights reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use 4 | these files except in compliance with the License. You may obtain a copy of the 5 | License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software distributed 10 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 11 | CONDITIONS OF ANY KIND, either express or implied. See the License for the 12 | specific language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/jquery-validation/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-validation", 3 | "homepage": "https://jqueryvalidation.org/", 4 | "repository": { 5 | "type": "git", 6 | "url": "git://github.com/jquery-validation/jquery-validation.git" 7 | }, 8 | "authors": [ 9 | "Jörn Zaefferer " 10 | ], 11 | "description": "Form validation made easy", 12 | "main": "dist/jquery.validate.js", 13 | "keywords": [ 14 | "forms", 15 | "validation", 16 | "validate" 17 | ], 18 | "license": "MIT", 19 | "ignore": [ 20 | "**/.*", 21 | "node_modules", 22 | "bower_components", 23 | "test", 24 | "demo", 25 | "lib" 26 | ], 27 | "dependencies": { 28 | "jquery": ">= 1.7.2" 29 | }, 30 | "version": "1.17.0", 31 | "_release": "1.17.0", 32 | "_resolution": { 33 | "type": "version", 34 | "tag": "1.17.0", 35 | "commit": "fc9b12d3bfaa2d0c04605855b896edb2934c0772" 36 | }, 37 | "_source": "https://github.com/jzaefferer/jquery-validation.git", 38 | "_target": "^1.17.0", 39 | "_originalSource": "jquery-validation", 40 | "_direct": true 41 | } -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/jquery-validation/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright Jörn Zaefferer 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/jquery/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery", 3 | "main": "dist/jquery.js", 4 | "license": "MIT", 5 | "ignore": [ 6 | "package.json" 7 | ], 8 | "keywords": [ 9 | "jquery", 10 | "javascript", 11 | "browser", 12 | "library" 13 | ], 14 | "homepage": "https://github.com/jquery/jquery-dist", 15 | "version": "3.3.1", 16 | "_release": "3.3.1", 17 | "_resolution": { 18 | "type": "version", 19 | "tag": "3.3.1", 20 | "commit": "9e8ec3d10fad04748176144f108d7355662ae75e" 21 | }, 22 | "_source": "https://github.com/jquery/jquery-dist.git", 23 | "_target": "^3.3.1", 24 | "_originalSource": "jquery", 25 | "_direct": true 26 | } -------------------------------------------------------------------------------- /Swift.Management/wwwroot/lib/jquery/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright JS Foundation and other contributors, https://js.foundation/ 2 | 3 | This software consists of voluntary contributions made by many 4 | individuals. For exact contribution history, see the revision history 5 | available at https://github.com/jquery/jquery 6 | 7 | The following license applies to all parts of this software except as 8 | documented below: 9 | 10 | ==== 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining 13 | a copy of this software and associated documentation files (the 14 | "Software"), to deal in the Software without restriction, including 15 | without limitation the rights to use, copy, modify, merge, publish, 16 | distribute, sublicense, and/or sell copies of the Software, and to 17 | permit persons to whom the Software is furnished to do so, subject to 18 | the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be 21 | included in all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | ==== 32 | 33 | All files located in the node_modules and external directories are 34 | externally maintained libraries used by this software which have their 35 | own licenses; we recommend you read them, as their terms may differ from 36 | the terms above. 37 | -------------------------------------------------------------------------------- /Swift.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27130.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Swift", "Swift\Swift.csproj", "{4300D8A0-4EAF-4F77-AC21-02A25BBE841A}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Swift.DemoJob", "Swift.DemoJob\Swift.DemoJob.csproj", "{EB486F4F-F948-4EA6-AE18-077628EF8048}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Swift.Core", "Swift.Core\Swift.Core.csproj", "{3066A32B-8B50-4D41-9C3F-2B662E23F1FD}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Swift.Management", "Swift.Management\Swift.Management.csproj", "{F37ECB6A-C51D-473A-8D10-A79580A251EB}" 13 | EndProject 14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docker", "docker", "{8D45B262-8EF6-4D80-83C6-38197159EE53}" 15 | ProjectSection(SolutionItems) = preProject 16 | Dockerfile = Dockerfile 17 | .dockerignore = .dockerignore 18 | docker-entrypoint.sh = docker-entrypoint.sh 19 | sources.list = sources.list 20 | EndProjectSection 21 | EndProject 22 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Swift.JobEntryPoint", "Swift.JobEntryPoint\Swift.JobEntryPoint.csproj", "{62AB4559-ADB4-4268-833F-F7FB0FB54F34}" 23 | EndProject 24 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E570DDA1-D9F4-4D5E-B9B2-3F7ED99F43E0}" 25 | ProjectSection(SolutionItems) = preProject 26 | README.md = README.md 27 | Todo.txt = Todo.txt 28 | EndProjectSection 29 | EndProject 30 | Global 31 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 32 | Debug|Any CPU = Debug|Any CPU 33 | Release|Any CPU = Release|Any CPU 34 | EndGlobalSection 35 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 36 | {4300D8A0-4EAF-4F77-AC21-02A25BBE841A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 37 | {4300D8A0-4EAF-4F77-AC21-02A25BBE841A}.Debug|Any CPU.Build.0 = Debug|Any CPU 38 | {4300D8A0-4EAF-4F77-AC21-02A25BBE841A}.Release|Any CPU.ActiveCfg = Release|Any CPU 39 | {4300D8A0-4EAF-4F77-AC21-02A25BBE841A}.Release|Any CPU.Build.0 = Release|Any CPU 40 | {EB486F4F-F948-4EA6-AE18-077628EF8048}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 41 | {EB486F4F-F948-4EA6-AE18-077628EF8048}.Debug|Any CPU.Build.0 = Debug|Any CPU 42 | {EB486F4F-F948-4EA6-AE18-077628EF8048}.Release|Any CPU.ActiveCfg = Release|Any CPU 43 | {EB486F4F-F948-4EA6-AE18-077628EF8048}.Release|Any CPU.Build.0 = Release|Any CPU 44 | {3066A32B-8B50-4D41-9C3F-2B662E23F1FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 45 | {3066A32B-8B50-4D41-9C3F-2B662E23F1FD}.Debug|Any CPU.Build.0 = Debug|Any CPU 46 | {3066A32B-8B50-4D41-9C3F-2B662E23F1FD}.Release|Any CPU.ActiveCfg = Release|Any CPU 47 | {3066A32B-8B50-4D41-9C3F-2B662E23F1FD}.Release|Any CPU.Build.0 = Release|Any CPU 48 | {F37ECB6A-C51D-473A-8D10-A79580A251EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 49 | {F37ECB6A-C51D-473A-8D10-A79580A251EB}.Debug|Any CPU.Build.0 = Debug|Any CPU 50 | {F37ECB6A-C51D-473A-8D10-A79580A251EB}.Release|Any CPU.ActiveCfg = Release|Any CPU 51 | {F37ECB6A-C51D-473A-8D10-A79580A251EB}.Release|Any CPU.Build.0 = Release|Any CPU 52 | {62AB4559-ADB4-4268-833F-F7FB0FB54F34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 53 | {62AB4559-ADB4-4268-833F-F7FB0FB54F34}.Debug|Any CPU.Build.0 = Debug|Any CPU 54 | {62AB4559-ADB4-4268-833F-F7FB0FB54F34}.Release|Any CPU.ActiveCfg = Release|Any CPU 55 | {62AB4559-ADB4-4268-833F-F7FB0FB54F34}.Release|Any CPU.Build.0 = Release|Any CPU 56 | EndGlobalSection 57 | GlobalSection(SolutionProperties) = preSolution 58 | HideSolutionNode = FALSE 59 | EndGlobalSection 60 | GlobalSection(ExtensibilityGlobals) = postSolution 61 | SolutionGuid = {476C188A-1C70-469D-B353-402DB9BEDA0A} 62 | EndGlobalSection 63 | EndGlobal 64 | -------------------------------------------------------------------------------- /Swift/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Swift/NLog.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 12 | 13 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Swift/Swift.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | bosima 7 | Swift服务程序。 8 | 0.1.0 9 | 0.1.0 10 | bosima 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Always 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Swift/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Warning" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /Swift/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Todo.txt: -------------------------------------------------------------------------------- 1 | 1、将Swift.Core中的日志操作转换为接口,在Swift项目中基于NLog实现日志处理 2 | 3 | 2、支持在管理UI上查看作业记录的执行日志。 4 | 5 | 3、将配置中心的操作(成员信息、作业记录信息等)抽象为接口,Consul KV只是默认的实现,也可以用MySQL来实现。 6 | 7 | 4、作业运行时不复制作业程序文件,仅在作业记录目录下记录各种状态、需求和结果,减少磁盘空间使用。 8 | 9 | 5、提供一个选项,让Manager也能执行任务,这个在某些不繁忙的场景比较节约资源。 10 | 11 | 6、在作业记录中记录制定计划的节点和完成合并的节点,方便使用磁盘存储时下载作业结果。 12 | 13 | 7、作业任务需求、作业结果等支持保存到其它存储中,比如阿里云OSS。 14 | 15 | 8、增加一个资源管理类,管理现在的Worker状态,在线Worker、Worker在执行的任务数等。 16 | 17 | 9、去掉任务和作业的Synced状态,每次合并任务结果时去拉取,降低处理的复杂度。 -------------------------------------------------------------------------------- /docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cluster='' 4 | consulboot=0 5 | consuljoinip='' 6 | 7 | until [ -z "$1" ] 8 | do 9 | IFS='=' read -ra argarray <<< "$1" 10 | if [ "${argarray[0]}" == '-cluster' ]; then 11 | cluster="${argarray[1]}" 12 | fi 13 | if [ "${argarray[0]}" == '-consulboot' ]; then 14 | consulboot=1 15 | fi 16 | if [ "${argarray[0]}" == '-consuljoinip' ]; then 17 | consuljoinip="${argarray[1]}" 18 | fi 19 | shift 20 | done 21 | 22 | if [ ! -n "$cluster" ]; then 23 | echo "Need Swift Cluster Name" && exit 1 24 | fi 25 | 26 | #consul 27 | CONSUL_DATA_DIR="/app/consul/data" 28 | CONSUL_BIND_INTERFACE="eth0" 29 | CONSUL_BIND= 30 | if [ -n "$CONSUL_BIND_INTERFACE" ]; then 31 | CONSUL_BIND_ADDRESS=$(ip -o -4 addr list $CONSUL_BIND_INTERFACE | head -n1 | awk '{print $4}' | cut -d/ -f1) 32 | if [ -z "$CONSUL_BIND_ADDRESS" ]; then 33 | echo "Could not find IP for interface '$CONSUL_BIND_INTERFACE', exiting" 34 | exit 1 35 | fi 36 | 37 | CONSUL_BIND="-bind=$CONSUL_BIND_ADDRESS" 38 | echo "==> Found address '$CONSUL_BIND_ADDRESS' for interface '$CONSUL_BIND_INTERFACE', setting consul bind option..." 39 | fi 40 | 41 | CONSUL_CLIENT= 42 | if [ -n "$CONSUL_CLIENT_INTERFACE" ]; then 43 | CONSUL_CLIENT_ADDRESS=$(ip -o -4 addr list $CONSUL_CLIENT_INTERFACE | head -n1 | awk '{print $4}' | cut -d/ -f1) 44 | if [ -z "$CONSUL_CLIENT_ADDRESS" ]; then 45 | echo "Could not find IP for interface '$CONSUL_CLIENT_INTERFACE', exiting" 46 | exit 1 47 | fi 48 | 49 | CONSUL_CLIENT="-client=$CONSUL_CLIENT_ADDRESS" 50 | echo "==> Found address '$CONSUL_CLIENT_ADDRESS' for interface '$CONSUL_CLIENT_INTERFACE', settin consul client option..." 51 | fi 52 | 53 | CONSUL_BOOT='' 54 | if [ "${consulboot}" = '1' ]; then 55 | CONSUL_BOOT="-bootstrap -server" 56 | fi 57 | 58 | CONSUL_JOIN= 59 | if [ -n "${consuljoinip}" ]; then 60 | CONSUL_JOIN="-retry-join "${consuljoinip}"" 61 | fi 62 | 63 | echo "${CONSUL_BOOT}" 64 | echo "consul is starting" 65 | nohup consul agent -datacenter=swiftdc ${CONSUL_BIND} ${CONSUL_CLIENT} -data-dir=${CONSUL_DATA_DIR} ${CONSUL_JOIN} ${CONSUL_BOOT} > /app/consul/log.txt 2>&1 & 66 | sleep 15s 67 | echo "consul has started" 68 | 69 | cd /app/management/ 70 | nohup dotnet /app/management/Swift.Management.dll --urls "http://0.0.0.0:9632" 2> /app/swift/error.txt > /dev/null & 71 | echo "management has started" 72 | 73 | nohup dotnet /app/swift/Swift.dll -c ${cluster} 2> /app/swift/error.txt > /dev/null & 74 | echo "swift has started" 75 | 76 | # https://github.com/vearne/graceful_docker/blob/master/entrypoint.sh 77 | 78 | while true; do echo hello world; sleep 3; done -------------------------------------------------------------------------------- /sources.list: -------------------------------------------------------------------------------- 1 | deb http://mirrors.ustc.edu.cn/debian/ stretch main non-free contrib 2 | deb http://mirrors.ustc.edu.cn/debian/ stretch-updates main non-free contrib 3 | deb http://mirrors.ustc.edu.cn/debian/ stretch-backports main non-free contrib 4 | deb-src http://mirrors.ustc.edu.cn/debian/ stretch main non-free contrib 5 | deb-src http://mirrors.ustc.edu.cn/debian/ stretch-updates main non-free contrib 6 | deb-src http://mirrors.ustc.edu.cn/debian/ stretch-backports main non-free contrib 7 | deb http://mirrors.ustc.edu.cn/debian-security/ stretch/updates main non-free contrib 8 | deb-src http://mirrors.ustc.edu.cn/debian-security/ stretch/updates main non-free contrib 9 | --------------------------------------------------------------------------------