├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── arbiter-cases
└── .gitignore
├── arbiter-docker
└── elk
│ ├── 02-beats-input.conf
│ ├── 30-output.conf
│ └── Dockerfile
├── arbiter-web
├── Dockerfile
├── Dockerfile_local
├── arbiter
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── asgi.py
│ ├── common
│ │ ├── __init__.py
│ │ └── utils.py
│ ├── core
│ │ ├── __init__.py
│ │ ├── apps.py
│ │ ├── consumers.py
│ │ ├── models.py
│ │ ├── routing.py
│ │ ├── templates
│ │ │ └── case
│ │ │ │ ├── component
│ │ │ │ ├── arbiter-navbar.vue
│ │ │ │ ├── case-float-btn.vue
│ │ │ │ ├── case-paper.vue
│ │ │ │ ├── code-float-btn.vue
│ │ │ │ ├── code-paper.vue
│ │ │ │ ├── menu-icon-button.vue
│ │ │ │ ├── nav-slide.vue
│ │ │ │ └── user-avatar.vue
│ │ │ │ ├── index.html
│ │ │ │ └── login.html
│ │ ├── tests.py
│ │ ├── urls.py
│ │ ├── util
│ │ │ ├── __init__.py
│ │ │ └── askpass.py
│ │ └── views.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ ├── 0002_case_run_info_status.py
│ │ ├── 0003_auto_20180214_1452.py
│ │ ├── 0004_auto_20180223_1416.py
│ │ ├── 0005_case_run_info_deleted.py
│ │ ├── 0006_auto_20180225_1306.py
│ │ └── __init__.py
│ ├── models.py
│ ├── routing.py
│ ├── settings.py
│ ├── static
│ │ └── arbiter
│ │ │ ├── css
│ │ │ ├── datatables
│ │ │ │ ├── dataTables.bootstrap.css
│ │ │ │ ├── dataTables.bootstrap.min.css
│ │ │ │ ├── dataTables.bootstrap4.css
│ │ │ │ ├── dataTables.bootstrap4.min.css
│ │ │ │ ├── dataTables.foundation.css
│ │ │ │ ├── dataTables.foundation.min.css
│ │ │ │ ├── dataTables.jqueryui.css
│ │ │ │ ├── dataTables.jqueryui.min.css
│ │ │ │ ├── dataTables.material.css
│ │ │ │ ├── dataTables.material.min.css
│ │ │ │ ├── dataTables.semanticui.css
│ │ │ │ ├── dataTables.semanticui.min.css
│ │ │ │ ├── dataTables.uikit.css
│ │ │ │ ├── dataTables.uikit.min.css
│ │ │ │ ├── jquery.dataTables.css
│ │ │ │ ├── jquery.dataTables.min.css
│ │ │ │ └── jquery.dataTables_themeroller.css
│ │ │ ├── element
│ │ │ │ ├── fonts
│ │ │ │ │ ├── element-icons.ttf
│ │ │ │ │ └── element-icons.woff
│ │ │ │ └── index.css
│ │ │ ├── index.css
│ │ │ ├── login.css
│ │ │ ├── material-icons.css
│ │ │ ├── materialize.css
│ │ │ ├── materialize.min.css
│ │ │ ├── muse
│ │ │ │ ├── muse-ui.css
│ │ │ │ ├── theme-teal.css
│ │ │ │ └── theme-teal.min.css
│ │ │ ├── navbar.css
│ │ │ ├── scrollbar
│ │ │ │ ├── app.css
│ │ │ │ └── vue2-scrollbar.css
│ │ │ └── wholog
│ │ │ │ ├── index.css
│ │ │ │ └── statistic-log.css
│ │ │ ├── fonts
│ │ │ ├── material
│ │ │ │ └── o_1bgljqsqrvbv78v8lu1fsr1trca.woff2
│ │ │ └── roboto
│ │ │ │ ├── Roboto-Bold.woff
│ │ │ │ ├── Roboto-Bold.woff2
│ │ │ │ ├── Roboto-Light.woff
│ │ │ │ ├── Roboto-Light.woff2
│ │ │ │ ├── Roboto-Medium.woff
│ │ │ │ ├── Roboto-Medium.woff2
│ │ │ │ ├── Roboto-Regular.woff
│ │ │ │ ├── Roboto-Regular.woff2
│ │ │ │ ├── Roboto-Thin.woff
│ │ │ │ └── Roboto-Thin.woff2
│ │ │ ├── imgs
│ │ │ ├── bg-pro.png
│ │ │ ├── favicon.ico
│ │ │ ├── progress.png
│ │ │ └── team_logo.png
│ │ │ └── js
│ │ │ ├── common
│ │ │ ├── ace
│ │ │ │ ├── ace.js
│ │ │ │ ├── mode-python.js
│ │ │ │ ├── theme-ambiance.js
│ │ │ │ ├── theme-chrome.js
│ │ │ │ ├── theme-dawn.js
│ │ │ │ ├── theme-github.js
│ │ │ │ └── theme-iplastic.js
│ │ │ ├── common.js
│ │ │ ├── element
│ │ │ │ └── index.js
│ │ │ ├── get-res.js
│ │ │ ├── index.js
│ │ │ ├── muse
│ │ │ │ └── muse-ui.js
│ │ │ ├── snow.js
│ │ │ └── vue
│ │ │ │ ├── vue-resource.js
│ │ │ │ ├── vue-resource.min.js
│ │ │ │ ├── vue-router.js
│ │ │ │ ├── vue-router.min.js
│ │ │ │ ├── vue.js
│ │ │ │ ├── vue.min.js
│ │ │ │ ├── vue2-scrollbar.js
│ │ │ │ └── vuex.js
│ │ │ ├── core
│ │ │ ├── app.js
│ │ │ ├── component
│ │ │ │ ├── arbiter-navbar.js
│ │ │ │ ├── arbiter-slide.js
│ │ │ │ ├── case-float-btn.js
│ │ │ │ ├── case-paper.js
│ │ │ │ ├── code-float-btn.js
│ │ │ │ ├── code-paper.js
│ │ │ │ ├── menu-icon-Button.js
│ │ │ │ └── user-avatar.js
│ │ │ └── route.js
│ │ │ ├── echarts.js
│ │ │ ├── login.js
│ │ │ ├── store.js
│ │ │ └── wholog
│ │ │ ├── app.js
│ │ │ ├── component
│ │ │ ├── header-components.js
│ │ │ ├── history-log.js
│ │ │ ├── log-slide.js
│ │ │ └── statistic-log.js
│ │ │ └── route.js
│ ├── urls.py
│ ├── wholog
│ │ ├── __init__.py
│ │ ├── admin.py
│ │ ├── apps.py
│ │ ├── models.py
│ │ ├── templates
│ │ │ ├── component
│ │ │ │ ├── arbiter-header.vue
│ │ │ │ ├── case-float-btn.vue
│ │ │ │ ├── history-log.vue
│ │ │ │ ├── log-slide.vue
│ │ │ │ ├── menu-icon-button.vue
│ │ │ │ ├── statistic-log.vue
│ │ │ │ └── user-avatar.vue
│ │ │ └── index.html
│ │ ├── tests.py
│ │ ├── urls.py
│ │ └── views.py
│ └── wsgi.py
├── config.py
├── docker-compose.yml
├── docker_start.sh
├── initadmin.py
├── manage.py
├── requirements.txt
└── stack-fix.c
├── doc
├── .gitignore
└── import.gif
└── tasks.todo
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.js linguist-language = python
2 | *.css linguist-language = python
3 | *.html linguist-language = python
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # IDEA Files #
3 |
4 | *.iml
5 | *.ipr
6 | *.iws
7 | *.idea
8 | *.history
9 |
10 | __pycache__
11 | !.gitignore
12 | arbiter-cases/*
13 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 | ## arbiter是什么
3 | - python实现的web IDE,可以导入&编辑脚本工程,进行测试执行和编辑的操作
4 | - 可以对测试日志进行查询和统计
5 |
6 | ## 依赖环境
7 | - postgresql存储用户信息
8 | - redis保证实时websocket
9 | - elk保存日志
10 |
11 | ## 部署步骤:
12 | 1. clone code
13 | 2. 进入到 arbiter-web/ cd arbiter-web
14 | 3. 安装依赖文件 pip install -r requirements.txt
15 | 4. 安装好postgresql redis elk。在config.py中修改成相对应的配置属性
16 | 5. 修改运行时选项,设置 manage.py路径,脚本命令为runserver
17 | 6. 或直接使用 python manage.py runserver
18 |
19 | ## 浏览器支持
20 | - chrome 60+
21 | - firefox 55+
22 |
23 | ##### 交流QQ:693411960
24 |
--------------------------------------------------------------------------------
/arbiter-cases/.gitignore:
--------------------------------------------------------------------------------
1 | # Eclipse Project Files #
2 |
3 | .classpath
4 | .project
5 | .settings
6 |
7 | # IntelliJ IDEA Files #
8 |
9 | *.iml
10 | *.ipr
11 | *.iws
12 | *.idea
13 |
--------------------------------------------------------------------------------
/arbiter-docker/elk/02-beats-input.conf:
--------------------------------------------------------------------------------
1 | input {
2 | redis {
3 | data_type =>"list"
4 | key => "logstash-arbiter-list"
5 | host =>"redis"
6 | port =>6379
7 | db =>11
8 | codec =>"json"
9 | }
10 | }
--------------------------------------------------------------------------------
/arbiter-docker/elk/30-output.conf:
--------------------------------------------------------------------------------
1 | output {
2 | elasticsearch {
3 | hosts => "localhost"
4 | index => "logstash-arbiter"
5 |
6 | }
7 | stdout {
8 | codec => rubydebug {}
9 | }
10 | }
--------------------------------------------------------------------------------
/arbiter-docker/elk/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM sebp/elk
2 |
3 | RUN rm -rf /etc/logstash/conf.d/02-beats-input.conf
4 | ADD ./02-beats-input.conf /etc/logstash/conf.d/02-beats-input.conf
5 | RUN rm -rf /etc/logstash/conf.d/30-output.conf
6 | ADD ./30-output.conf /etc/logstash/conf.d/30-output.conf
--------------------------------------------------------------------------------
/arbiter-web/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.6.2-alpine
2 |
3 | RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
4 | RUN apk add --no-cache postgresql-dev libffi-dev gcc musl-dev libxml2-dev libxslt-dev git bash
5 | WORKDIR /usr/src/app
6 | COPY . .
7 | RUN gcc -shared -fPIC stack-fix.c -o stack-fix.so
8 | ENV LD_PRELOAD = /usr/src/app/stack-fix.so
9 | RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn
10 | #RUN pip install --no-cache-dir -r requirements.txt
11 | EXPOSE 8000:8000
12 |
13 | CMD sh docker_start.sh
--------------------------------------------------------------------------------
/arbiter-web/Dockerfile_local:
--------------------------------------------------------------------------------
1 | FROM shimine/cua-arbiter:1.3-alpine
2 |
3 | WORKDIR /usr/src/app
4 | COPY . .
5 |
6 | CMD sh docker_start.sh
--------------------------------------------------------------------------------
/arbiter-web/arbiter/__init__.py:
--------------------------------------------------------------------------------
1 | default_app_config = 'arbiter.apps.CaseManagerConfig'
--------------------------------------------------------------------------------
/arbiter-web/arbiter/admin.py:
--------------------------------------------------------------------------------
1 | from django import forms
2 | from django.contrib import admin
3 | from django.contrib.auth import get_user_model
4 | from django.contrib.admin.widgets import FilteredSelectMultiple
5 | from django.contrib.auth.models import Group
6 |
7 | admin.AdminSite.site_header = "arbiter接口测试数据管理"
8 |
9 | User = get_user_model()
10 |
11 |
12 | # Create ModelForm based on the Group model.
13 | class GroupAdminForm(forms.ModelForm):
14 | class Meta:
15 | model = Group
16 | exclude = []
17 |
18 | # Add the users field.
19 | users = forms.ModelMultipleChoiceField(
20 | queryset=User.objects.all(),
21 | required=False,
22 | # Use the pretty 'filter_horizontal widget'.
23 | widget=FilteredSelectMultiple('users', False)
24 | )
25 |
26 | def __init__(self, *args, **kwargs):
27 | # Do the normal form initialisation.
28 | super(GroupAdminForm, self).__init__(*args, **kwargs)
29 | # If it is an existing group (saved objects have a pk).
30 | if self.instance.pk:
31 | # Populate the users field with the current Group users.
32 | self.fields['users'].initial = self.instance.user_set.all()
33 |
34 | def save_m2m(self):
35 | # Add the users to the Group.
36 | self.instance.user_set = self.cleaned_data['users']
37 |
38 | def save(self, *args, **kwargs):
39 | # Default save
40 | instance = super(GroupAdminForm, self).save()
41 | # Save many-to-many data
42 | self.save_m2m()
43 | return instance
44 |
45 |
46 | # Unregister the original Group admin.
47 | admin.site.unregister(Group)
48 |
49 |
50 | # Create a new Group admin.
51 | class GroupAdmin(admin.ModelAdmin):
52 | # Use our custom form.
53 | form = GroupAdminForm
54 | # Filter permissions horizontal as well.
55 | filter_horizontal = ['permissions']
56 |
57 |
58 | # Register the new Group ModelAdmin.
59 | admin.site.register(Group, GroupAdmin)
60 | # Register your models here.
61 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/apps.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | from django.apps import AppConfig
4 |
5 |
6 | class CaseManagerConfig(AppConfig):
7 | name = 'arbiter'
8 |
9 | def ready(self):
10 | case_base_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))),
11 | "arbiter-cases")
12 | case_path = os.getenv("CASEPATH")
13 | case_base_path = os.path.join(case_base_path, case_path.split('/')[0])
14 | case_base_path = case_base_path.replace("\\", "/")
15 | os.environ["PYTHONPATH"] = case_base_path
16 | os.putenv("PYTHONPATH", case_base_path)
17 | from arbiter.models import Git_Info
18 | from arbiter.core.models import CaseList
19 | from arbiter.models import Case_List
20 | try:
21 | if Git_Info.objects.count() > 0:
22 | git_info = Git_Info.objects.all().first()
23 | os.environ['GIT_USERNAME'] = git_info.user_name
24 | os.environ['GIT_PASSWORD'] = git_info.password
25 | case_list = Case_List.objects.get()
26 | case_list.name = "arbiter_cases"
27 | case_list.data = CaseList.getList()
28 | case_list.save()
29 | except:
30 | pass
31 | os.environ['GIT_ASKPASS'] = os.path.join(
32 | os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'core'), 'util'),
33 | 'askpass.py')
34 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/asgi.py:
--------------------------------------------------------------------------------
1 | import os
2 | import channels.asgi
3 |
4 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "arbiter.settings") # 这里填的是你的配置文件settings.py的位置
5 | channel_layer = channels.asgi.get_channel_layer()
6 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/common/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuaFramework/cua-arbiter/61b2ea5d8b7c825b75d0f333d202e5703e0565a9/arbiter-web/arbiter/common/__init__.py
--------------------------------------------------------------------------------
/arbiter-web/arbiter/common/utils.py:
--------------------------------------------------------------------------------
1 | import time
2 | import datetime
3 | import hashlib
4 |
5 |
6 | # 生成uuid
7 | def generate_id():
8 | m = hashlib.md5(str(time.clock()).encode('utf-8'))
9 | return m.hexdigest()
10 |
11 |
12 | # 获取当前时间
13 | # typeid=1 ,格式:2017-09-05 13:58:41
14 | # typeid=1 ,格式:时间戳形式:1505112338.4971874
15 | def get_now_time(type_id):
16 | if type_id == 1:
17 | return datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')
18 | if type_id == 2:
19 | return datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%fZ')
20 |
21 |
22 | # 处理logData数据
23 | def get_log_data(log_data):
24 | log_str = log_data.split("请求")[1].split("]")[0] # 获得请求类型+耗时+code部分数据
25 | if log_str is not None:
26 | result_list = log_str.split(" ")
27 | type_value = result_list[0].split(":")[1]
28 | consume_time = result_list[1].split(":")[1].split("m")[0]
29 | response_code = result_list[2].split(":")[1]
30 | response_value = {"request_type": type_value, "consume_time": consume_time, "response_code": response_code}
31 | return response_value
32 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/core/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuaFramework/cua-arbiter/61b2ea5d8b7c825b75d0f333d202e5703e0565a9/arbiter-web/arbiter/core/__init__.py
--------------------------------------------------------------------------------
/arbiter-web/arbiter/core/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class CoreConfig(AppConfig):
5 | name = 'arbiter.core'
6 |
7 |
8 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/core/consumers.py:
--------------------------------------------------------------------------------
1 | from subprocess import Popen, PIPE, STDOUT
2 | from channels.sessions import channel_session
3 | from arbiter.models import Case_Run_Info
4 | from ..settings import redis_elk_pool
5 | import json
6 | import redis
7 | from ..common import utils
8 |
9 | # 一个管道大概会持续30s
10 |
11 |
12 | isEditFilesName = [] # 全局变量,保存正在被编辑的文件名
13 | # redis 配置
14 |
15 | # logstash 在redis key值
16 | logstash_redis_key = 'logstash-arbiter-list'
17 | # redis 连接
18 | re = redis.Redis(connection_pool=redis_elk_pool)
19 |
20 |
21 | # 当连接上时,发回去一个connect字符串
22 | @channel_session
23 | def ws_connect(message):
24 | message.reply_channel.send({"accept": True})
25 |
26 |
27 | # 将发来的信息原样返回
28 | @channel_session
29 | def ws_message(message):
30 | cmd = message.content['text']
31 | log_content = ''
32 | # 获得本次运行的用例id
33 | log_id = utils.generate_id()
34 | # 通过自定义字符分割需要的类型
35 | if cmd.split(' ')[0] == 'runCase':
36 | message.reply_channel.send({
37 | "text": "**********************************************开始执行***********************************************"
38 | }, immediately=True)
39 | case_name = cmd.split(' ')[1]
40 | user_name = cmd.split(' ')[2]
41 | task_name = cmd.split(' ')[3]
42 | run_time = utils.get_now_time(1)
43 | runcmd = Popen(['nosetests', '-P', '--nologcapture', case_name],
44 | bufsize=0, stdout=PIPE, stderr=STDOUT)
45 | text = None
46 | while True:
47 | line = runcmd.stdout.readline()
48 | if not line:
49 | break
50 | text = line.decode('utf-8')
51 | if 'Ran' in text and 'test' in text:
52 | info_text = text
53 | # 拼接日志内容
54 | case_name = case_name
55 | create_time = utils.get_now_time(2)
56 | data = {'create_time': create_time, 'logId': log_id, 'case': case_name, 'author': user_name,
57 | 'logData': text}
58 | # 向redis中发送值
59 | logData = json.dumps(data)
60 | re.lpush(logstash_redis_key, logData)
61 | message.reply_channel.send({
62 | "text": text
63 | }, immediately=True)
64 |
65 | message.reply_channel.send({
66 | "text": "**********************************************结束执行***********************************************"
67 | }, immediately=True)
68 | num = info_text.split("Ran")[1].split("test")[0].strip()
69 | duration = info_text.split(" in")[1].split("s")[0].strip()
70 | # 存一条logId到mysql
71 | # 将日志存入mysql
72 | # mysql 存入格式和内容需要完善
73 | dic = {'log_id': log_id, 'case_name': case_name, 'run_time': run_time, 'author': user_name,
74 | 'duration': duration, 'num': num,
75 | 'task_name': task_name, 'result': text.split("(")[0].strip().replace("\n", "")}
76 | Case_Run_Info.objects.create(**dic)
77 |
78 | if cmd.split(' ')[0] == 'validateEdit':
79 |
80 | if cmd.split(' ')[1] == '0':
81 | if cmd.split(' ')[2] in isEditFilesName:
82 | message.reply_channel.send({
83 | "text": "isBusy"
84 | }, immediately=True)
85 | isEditFilesName.append(cmd.split(' ')[2])
86 | if cmd.split(' ')[1] == '1':
87 | isEditFilesName.remove(cmd.split(' ')[2])
88 |
89 |
90 | # 断开连接时发送一个disconnect字符串
91 | @channel_session
92 | def ws_disconnect(message):
93 | message.reply_channel.send({"disc": True})
94 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/core/models.py:
--------------------------------------------------------------------------------
1 | from __future__ import unicode_literals
2 | from subprocess import Popen, PIPE, STDOUT
3 | import os
4 | from django.contrib.auth.models import Group
5 |
6 |
7 | # Create your models here.
8 | # case模型
9 | def Splitmap(src_map, i):
10 | dst_map = {}
11 | for case_path, case_name in src_map.items():
12 | path_arry = case_path.split(":")[0].split(".")
13 | if len(path_arry) > i + 1:
14 | if path_arry[i] not in dst_map:
15 | dst_map[path_arry[i]] = {}
16 | dst_map[path_arry[i]][case_path] = case_name
17 | else:
18 | dst_map[case_path] = case_name
19 | i = i + 1
20 | for k, y in dst_map.items():
21 | if isinstance(y, dict):
22 | dst_map[k] = Splitmap(y, i)
23 | return dst_map
24 |
25 |
26 | def restructure(src_map):
27 | dst_map = {}
28 | for model, cases in src_map.items():
29 | if model not in dst_map:
30 | dst_map[model] = {}
31 | dst_map[model] = Splitmap(cases, 2)
32 | return dst_map
33 |
34 |
35 | class CaseList:
36 |
37 | @staticmethod
38 | def getList():
39 | runcmd = Popen(['nosetests', '-vvv', '--collect-only', '-w', '../arbiter-cases'], bufsize=0,
40 | stdout=PIPE, stderr=STDOUT)
41 | log_list = []
42 | case_path = os.getenv("CASEPATH")
43 | case_path_obj = case_path.split('/')[0]
44 | case_path_fd = case_path.split('/')[1]
45 | case_class = case_path_obj + "." + case_path_fd
46 | for line in runcmd.stdout:
47 | log_list.append(line.decode('utf-8').rstrip())
48 | # 修改显示名称
49 | case_list = []
50 | res_tree = {}
51 | case_map = {}
52 | case_name = None
53 | for elem in log_list:
54 | if elem.find("Preparing test case ") != -1:
55 | if elem.find("(") != -1:
56 | x = elem.split("Preparing test case ")[1]
57 | temp = x.split(" (" + case_path_obj + ".")[1].split(")")[0] + "." + x.split(" (")[0]
58 | else:
59 | temp = elem.split("Preparing test case " + case_path_obj + ".")[1]
60 |
61 | model = temp.split(".")[1]
62 | case_name = temp[::-1].replace(".", ":", 2).replace(":", ".", 1)[::-1]
63 | if model not in res_tree:
64 | res_tree[model] = {}
65 | case_map = res_tree[model]
66 | case_map[case_name] = temp[::-1].replace(".", ":", 2).replace(":", ".", 1)[::-1]
67 | case_list.append(
68 | temp[::-1].replace(".", ":", 2).replace(":", ".", 1)[::-1])
69 | elif elem.find(" ... ok") != -1:
70 | des_str = elem.split(" ...")[0]
71 | if elem.find("(") != -1:
72 | temp_str = des_str.split(")")[0].split(".")
73 | des_str = temp_str[len(temp_str) - 1] + "." + des_str.split(" (")[0]
74 | if case_class in des_str:
75 | des_str = des_str.split(case_class + ".")[1].split(".", 1)[1]
76 | case_map[case_name] = des_str
77 | res_tree = restructure(res_tree)
78 | return res_tree
79 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/core/routing.py:
--------------------------------------------------------------------------------
1 | from channels.routing import route
2 |
3 | from . import consumers
4 |
5 | case_manager_routing = [
6 | # route("http.request", consumers.http_consumer), 这个表项比较特殊,他响应的是http.request,也就是说有HTTP请求时就会响应,同时urls.py里面的表单会失效
7 | route("websocket.connect", consumers.ws_connect), # 当WebSocket请求连接上时调用consumers.ws_connect函数
8 | route("websocket.receive", consumers.ws_message), # 当WebSocket请求发来消息时。。。
9 | route("websocket.disconnect", consumers.ws_disconnect), # 当WebSocket请求断开连接时。。。
10 | ]
11 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/core/templates/case/component/arbiter-navbar.vue:
--------------------------------------------------------------------------------
1 | {% verbatim %}
2 |
3 |
4 |
5 |
6 | 用例管理
7 |
8 |
10 |
11 |
13 |
15 |
16 |
17 |
18 |
19 | {% endverbatim %}
--------------------------------------------------------------------------------
/arbiter-web/arbiter/core/templates/case/component/case-float-btn.vue:
--------------------------------------------------------------------------------
1 | {% verbatim %}
2 |
3 |
4 |
6 |
9 |
10 |
11 |
12 |
14 | {{ log }}
15 |
16 |
18 |
19 |
20 |
21 |
22 | {% endverbatim %}
--------------------------------------------------------------------------------
/arbiter-web/arbiter/core/templates/case/component/case-paper.vue:
--------------------------------------------------------------------------------
1 | {% verbatim %}
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | {{ key }}
10 |
12 |
13 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
39 |
41 |
43 |
44 |
45 |
46 |
47 |
48 |
50 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | {% endverbatim %}
--------------------------------------------------------------------------------
/arbiter-web/arbiter/core/templates/case/component/code-float-btn.vue:
--------------------------------------------------------------------------------
1 | {% verbatim %}
2 |
3 |
4 |
6 |
8 |
9 |
10 |
11 |
13 |
14 |
15 |
16 |
18 | {{ log }}
19 |
20 |
22 |
23 |
24 |
25 |
26 | {% endverbatim %}
--------------------------------------------------------------------------------
/arbiter-web/arbiter/core/templates/case/component/code-paper.vue:
--------------------------------------------------------------------------------
1 | {% verbatim %}
2 |
3 |
6 |
7 | {% endverbatim %}
--------------------------------------------------------------------------------
/arbiter-web/arbiter/core/templates/case/component/menu-icon-button.vue:
--------------------------------------------------------------------------------
1 | {% verbatim %}
2 |
15 | {% endverbatim %}
--------------------------------------------------------------------------------
/arbiter-web/arbiter/core/templates/case/component/nav-slide.vue:
--------------------------------------------------------------------------------
1 | {% verbatim %}
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
19 |
20 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
34 |
37 |
40 |
42 |
44 |
45 |
46 |
47 |
48 | {% endverbatim %}
--------------------------------------------------------------------------------
/arbiter-web/arbiter/core/templates/case/component/user-avatar.vue:
--------------------------------------------------------------------------------
1 | {% verbatim %}
2 |
3 |
4 | {{ usernameAbbreviation }}
6 |
7 |
10 |
11 |
12 |
13 |
14 |
16 |
17 |
18 |
19 |
20 | {% endverbatim %}
21 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/core/templates/case/index.html:
--------------------------------------------------------------------------------
1 | {% load static %}
2 | {% load i18n %}
3 | {% load staticfiles %}
4 |
5 |
6 |
7 |
8 |
9 |
10 | arbiter
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | {% block head %}
19 | {% endblock head %}
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | {% verbatim %}
31 |
45 | {% endverbatim %}
46 |
47 | {% include "case/component/menu-icon-button.vue" %}
48 | {% include "case/component/user-avatar.vue" %}
49 | {% include "case/component/arbiter-navbar.vue" %}
50 | {% include "case/component/nav-slide.vue" %}
51 | {% include "case/component/case-paper.vue" %}
52 | {% include "case/component/code-paper.vue" %}
53 | {% include "case/component/code-float-btn.vue" %}
54 | {% include "case/component/case-float-btn.vue" %}
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/core/templates/case/login.html:
--------------------------------------------------------------------------------
1 | {% load static %}
2 | {% load i18n %}
3 | {% load staticfiles %}
4 |
5 |
6 |
7 |
8 |
9 |
10 | 登录
11 |
12 |
13 |
14 |
15 | {% block head %}
16 | {% endblock head %}
17 |
18 |
19 |
20 |
21 | {% verbatim %}
22 |
42 | {% endverbatim %}
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/core/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 | from arbiter.common import utils
3 | import re
4 |
5 |
6 | # Create your tests here.
7 | class Test:
8 |
9 | def id_test(self):
10 | log_id = utils.generate_id()
11 | print(log_id)
12 |
13 | def spilt_demo(self):
14 | text = "2017-12-27 10:09:12,655 - INFO - [https://www.v2ex.com:443/signin {} {} " \
15 | "请求类型:GET 耗时:215.734ms 返回码:200] - at utils.arbiter_logger.get_response(http_client.py:38)"
16 | t1 = text.split("请求")[1].split("]")[0]
17 | print(t1)
18 | result_str = t1.split(" ")
19 | print(result_str)
20 | type = result_str[0].split(":")[1]
21 | time = result_str[1].split(":")[1].split("m")[0]
22 | code = result_str[2].split(":")[1]
23 |
24 | print("type:"+type+"time:"+time+"code:"+code)
25 |
26 | if __name__ == '__main__':
27 | test = Test()
28 | result = test.spilt_demo()
29 |
30 |
31 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/core/urls.py:
--------------------------------------------------------------------------------
1 | from django.conf.urls import url
2 | from . import views
3 | from rest_framework_jwt.views import obtain_jwt_token
4 |
5 | urlpatterns = [
6 | url(r'^login', views.login, name='login'),
7 | url(r'^api-token-auth', obtain_jwt_token),
8 | url(r'^getUserDetail', views.auth_restful.get_user_detail),
9 | url(r'^save', views.auth_restful.save_case_file, name='save'),
10 | url(r'^delete', views.auth_restful.delete_case_file, name='delete'),
11 | url(r'^copy', views.auth_restful.copy_case_file, name='copy'),
12 | url(r'^getCaseList', views.restful.get_case_list),
13 | url(r'^cloneCaseObj', views.restful.get_caseobj),
14 | url(r'^$', views.index, name='index'),
15 | url(r'^.*$', views.index),
16 | ]
17 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/core/util/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuaFramework/cua-arbiter/61b2ea5d8b7c825b75d0f333d202e5703e0565a9/arbiter-web/arbiter/core/util/__init__.py
--------------------------------------------------------------------------------
/arbiter-web/arbiter/core/util/askpass.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | # Short & sweet script for use with git clone and fetch credentials.
4 | # Requires GIT_USERNAME and GIT_PASSWORD environment variables,
5 | # intended to be called by Git via GIT_ASKPASS.
6 | #
7 |
8 | from sys import argv
9 | from os import environ
10 |
11 | if "Username for" in argv[1]:
12 | print(environ['GIT_USERNAME'])
13 | exit()
14 |
15 | if "Password for" in argv[1]:
16 | print(environ['GIT_PASSWORD'])
17 | exit()
18 |
19 | exit(1)
20 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/core/views.py:
--------------------------------------------------------------------------------
1 | import codecs
2 | import json
3 | import os
4 | import stat
5 | import shutil
6 | import time
7 | import git
8 | from django.core.files import File
9 | from django.http import HttpResponse, JsonResponse
10 | from django.shortcuts import render
11 | from rest_framework import permissions
12 | from rest_framework.authtoken.models import Token
13 | from rest_framework.decorators import api_view, permission_classes
14 | from rest_framework.permissions import IsAuthenticated
15 | from rest_framework.views import APIView
16 |
17 | from arbiter.core.models import CaseList
18 | from arbiter.models import Case_List, Git_Info
19 |
20 |
21 | # 登录
22 | def login(request):
23 | return render(request, 'case/login.html')
24 |
25 |
26 | def index(request):
27 | return render(request, 'case/index.html')
28 |
29 |
30 | class restful(APIView):
31 | # 获取测试用例树
32 | def __init__(self, **kwargs):
33 | super().__init__(**kwargs)
34 | self.body = None
35 |
36 | @api_view(['POST'])
37 | @permission_classes([permissions.AllowAny, ])
38 | def get_case_list(self):
39 | try:
40 | cases_results = Case_List.objects.filter(name="arbiter_cases").first().data
41 | return JsonResponse(cases_results)
42 | except AttributeError:
43 | cases_results = CaseList.getList()
44 | Case_List.objects.create(name="arbiter_cases", data=cases_results)
45 | return JsonResponse(cases_results)
46 |
47 | # 获取测试用例GIT工程
48 | @api_view(['POST'])
49 | @permission_classes([permissions.AllowAny, ])
50 | def get_caseobj(self):
51 | case_path = os.getenv("CASEPATH")
52 | json_obj = json.loads(self.body)
53 | if Git_Info.objects.count() > 0:
54 | info = Git_Info.objects.get()
55 | info.git_url = json_obj.get('url')
56 | info.user_name = json_obj.get("git_username")
57 | info.password = json_obj.get("git_password")
58 | info.save()
59 |
60 | def set_rw(operation, name, exc):
61 | os.chmod(name, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
62 | os.remove(name)
63 | return True
64 |
65 | shutil.rmtree('../arbiter-cases', onerror=set_rw)
66 | else:
67 | Git_Info.objects.create(user_name=json_obj.get("git_username"), password=json_obj.get("git_password"),
68 | git_url=json_obj.get('url'))
69 |
70 | repo = git.Repo.clone_from(json_obj.get('url'), '../arbiter-cases/' + case_path.split('/')[0], branch='master')
71 | response_data = {'success': True}
72 | if Case_List.objects.count() > 0:
73 | case_list = Case_List.objects.get()
74 | case_list.name = "arbiter_cases"
75 | case_list.data = CaseList.getList()
76 | case_list.save()
77 | else:
78 | Case_List.objects.create(name="arbiter_cases", data=CaseList.getList())
79 | return JsonResponse(response_data)
80 |
81 |
82 | # 下列接口需要登录验证
83 | class auth_restful(APIView):
84 | # 设置permission_classes为必须登陆才能访问下列接口
85 | permission_classes = (IsAuthenticated,)
86 |
87 | # 获取用户信息
88 | def __init__(self, **kwargs):
89 | super().__init__(**kwargs)
90 | self.user = None
91 | self.method = None
92 | self.body = None
93 |
94 | @api_view(['POST'])
95 | def get_user_detail(self):
96 | response_data = {'username': self.user.username,
97 | 'role': list(self.user.groups.values_list('name', flat=True))}
98 | return JsonResponse(response_data)
99 |
100 | # 注销
101 | @api_view(['GET'])
102 | def logout(self):
103 | Token.objects.get(user_id=self.user.id).delete()
104 | Token.objects.create(user_id=self.user.id)
105 | response_data = {'success': True}
106 | return JsonResponse(response_data, content_type="application/json")
107 |
108 | # 复制文件方法
109 | @api_view(['POST'])
110 | def copy_case_file(self):
111 | case_path = os.getenv("CASEPATH")
112 | # 获取发送的请求
113 | json_str = self.body
114 | json_obj = json.loads(json_str)
115 | git_path = '../arbiter-cases/' + case_path.split("/")[0]
116 | root_path = '../arbiter-cases/' + case_path + '/'
117 | old_case_path = json_obj.get('oldPath')
118 | new_case_path = json_obj.get('newPath')
119 | shutil.copyfile(root_path + old_case_path,
120 | root_path + new_case_path)
121 | repo = git.Repo(git_path)
122 | repo_index = repo.index
123 | repo_index.add([case_path.split("/")[1] + "/" + new_case_path])
124 | repo_index.commit(self.user.username + "复制文件" + old_case_path + "到" + new_case_path)
125 | # 获取远程仓库
126 | remote = repo.remote()
127 | remote.pull()
128 | # 推送本地修改到远程仓库
129 | remote.push()
130 | # 同步最新用例列表到数据库
131 | case_list = Case_List.objects.get()
132 | case_list.name = "arbiter_cases"
133 | case_list.data = CaseList.getList()
134 | case_list.save()
135 | return HttpResponse(json.dumps({"result": 'ok'}), content_type="application/json")
136 | # 复制文件方法
137 |
138 | @api_view(['POST'])
139 | def delete_case_file(self):
140 | case_path = os.getenv("CASEPATH")
141 | # 获取发送的请求
142 | json_str = self.body
143 | json_obj = json.loads(json_str)
144 | git_path = '../arbiter-cases/' + case_path.split("/")[0]
145 | root_path = '../arbiter-cases/' + case_path + '/'
146 | delete_case_path = case_path = json_obj.get('deleteFilePath')
147 | os.remove(root_path + delete_case_path)
148 | repo = git.Repo(git_path)
149 | repo.git.add(update=True)
150 | repo_index = repo.index
151 | repo_index.commit(self.user.username + "删除文件" + delete_case_path)
152 | # 获取远程仓库
153 | remote = repo.remote()
154 | remote.pull()
155 | # 推送本地修改到远程仓库
156 | remote.push()
157 | # 同步最新用例列表到数据库
158 | case_list = Case_List.objects.get()
159 | case_list.name = "arbiter_cases"
160 | case_list.data = CaseList.getList()
161 | case_list.save()
162 | return HttpResponse(json.dumps({"result": 'ok'}), content_type="application/json")
163 |
164 | # 保存文件方法
165 | @api_view(['POST'])
166 | def save_case_file(self):
167 | case_path = os.getenv("CASEPATH")
168 | case_path_obj = case_path.split('/')[0]
169 | # 获取发送的请求
170 | json_str = self.body
171 | json_obj = json.loads(json_str)
172 | case_path = json_obj.get('casepath').split(':')[0].replace('.', '/') + '.py'
173 | time_str = time.strftime("%Y-%m-%d %H_%M_%S")
174 | # rename 原文件+时间格式(2017-07-20 18_34_48)
175 | os.rename('../arbiter-cases/' + case_path_obj + '/' + case_path,
176 | '../arbiter-cases/' + case_path_obj + '/' + case_path + '_' + time_str + '.history')
177 | # 使用codecs解决乱码问题
178 | with codecs.open('../arbiter-cases/' + case_path_obj + '/' + case_path, 'w', 'utf-8') as f:
179 | mfile = File(f)
180 | mfile.write(json_obj.get('content'))
181 | mfile.flush()
182 | mfile.seek(0)
183 | mfile.close()
184 | if mfile.closed:
185 | result = 'ok'
186 | repo = git.Repo('../arbiter-cases/' + case_path_obj)
187 | repo.git.add(update=True)
188 | repo_index = repo.index
189 | repo_index.commit(self.user.username + "修改文件" + case_path)
190 | # 获取远程仓库
191 | remote = repo.remote()
192 | remote.pull()
193 | # 推送本地修改到远程仓库
194 | remote.push()
195 | # 同步最新用例列表到数据库
196 | case_list = Case_List.objects.get()
197 | case_list.name = "arbiter_cases"
198 | case_list.data = CaseList.getList()
199 | case_list.save()
200 | return HttpResponse(json.dumps({"result": result}), content_type="application/json")
201 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.11.7 on 2018-02-11 09:59
3 | from __future__ import unicode_literals
4 |
5 | import django.contrib.postgres.fields.jsonb
6 | from django.db import migrations, models
7 | import django.utils.timezone
8 |
9 |
10 | class Migration(migrations.Migration):
11 |
12 | initial = True
13 |
14 | dependencies = [
15 | ]
16 |
17 | operations = [
18 | migrations.CreateModel(
19 | name='Case_List',
20 | fields=[
21 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
22 | ('name', models.CharField(max_length=200)),
23 | ('data', django.contrib.postgres.fields.jsonb.JSONField()),
24 | ],
25 | ),
26 | migrations.CreateModel(
27 | name='Case_Run_Info',
28 | fields=[
29 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
30 | ('log_id', models.UUIDField()),
31 | ('case_name', models.TextField(max_length=200)),
32 | ('run_time', models.DateTimeField()),
33 | ('author', models.CharField(max_length=50)),
34 | ('result', models.CharField(default='done', max_length=50)),
35 | ('version', models.IntegerField(default='10000000')),
36 | ],
37 | ),
38 | migrations.CreateModel(
39 | name='Case_Save_Info',
40 | fields=[
41 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
42 | ('case_name', models.TextField(max_length=200)),
43 | ('version', models.IntegerField(default=10000000)),
44 | ('author', models.CharField(max_length=50)),
45 | ('save_time', models.DateTimeField(default=django.utils.timezone.now)),
46 | ],
47 | ),
48 | migrations.CreateModel(
49 | name='Case_Version_Info',
50 | fields=[
51 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
52 | ('case_name', models.TextField(max_length=200)),
53 | ('latest_version', models.IntegerField(default=10000000)),
54 | ('update_time', models.DateTimeField(default=django.utils.timezone.now)),
55 | ],
56 | ),
57 | migrations.CreateModel(
58 | name='Git_Info',
59 | fields=[
60 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
61 | ('user_name', models.CharField(max_length=50)),
62 | ('password', models.CharField(max_length=50)),
63 | ],
64 | ),
65 | ]
66 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/migrations/0002_case_run_info_status.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.11.7 on 2018-02-13 03:00
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('arbiter', '0001_initial'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='case_run_info',
17 | name='status',
18 | field=models.CharField(default='done', max_length=50),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/migrations/0003_auto_20180214_1452.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.11.7 on 2018-02-14 06:52
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('arbiter', '0002_case_run_info_status'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='case_run_info',
17 | name='task_name',
18 | field=models.TextField(default='noName', max_length=200),
19 | ),
20 | migrations.AlterField(
21 | model_name='case_run_info',
22 | name='case_name',
23 | field=models.TextField(max_length=5000),
24 | ),
25 | ]
26 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/migrations/0004_auto_20180223_1416.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.11.7 on 2018-02-23 06:16
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('arbiter', '0003_auto_20180214_1452'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='case_run_info',
17 | name='duration',
18 | field=models.CharField(default='0', max_length=50),
19 | ),
20 | migrations.AddField(
21 | model_name='case_run_info',
22 | name='num',
23 | field=models.CharField(default='0', max_length=50),
24 | ),
25 | ]
26 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/migrations/0005_case_run_info_deleted.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.11.7 on 2018-02-24 09:59
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('arbiter', '0004_auto_20180223_1416'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='case_run_info',
17 | name='deleted',
18 | field=models.IntegerField(default=0, max_length=50),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/migrations/0006_auto_20180225_1306.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.11.5 on 2018-02-25 05:06
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('arbiter', '0005_case_run_info_deleted'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='git_info',
17 | name='git_url',
18 | field=models.CharField(default='null', max_length=200),
19 | ),
20 | migrations.AlterField(
21 | model_name='case_run_info',
22 | name='deleted',
23 | field=models.IntegerField(default=0),
24 | ),
25 | migrations.AlterField(
26 | model_name='case_run_info',
27 | name='result',
28 | field=models.CharField(default='FAILED', max_length=50),
29 | ),
30 | ]
31 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuaFramework/cua-arbiter/61b2ea5d8b7c825b75d0f333d202e5703e0565a9/arbiter-web/arbiter/migrations/__init__.py
--------------------------------------------------------------------------------
/arbiter-web/arbiter/models.py:
--------------------------------------------------------------------------------
1 | from __future__ import unicode_literals
2 | from django.db import models
3 | from django.contrib.auth.models import Group
4 | from django.contrib.postgres.fields import JSONField
5 | import django.utils.timezone as timezone
6 |
7 |
8 | # GIT权限信息
9 | class Git_Info(models.Model):
10 | git_url = models.CharField(max_length=200, default='null')
11 | user_name = models.CharField(max_length=50)
12 | password = models.CharField(max_length=50)
13 |
14 |
15 | # 用例列表
16 | class Case_List(models.Model):
17 | name = models.CharField(max_length=200)
18 | data = JSONField()
19 |
20 |
21 | # 运行日志信息模型
22 | class Case_Run_Info(models.Model):
23 | log_id = models.UUIDField()
24 | task_name = models.TextField(max_length=200, default='noName')
25 | case_name = models.TextField(max_length=5000)
26 | run_time = models.DateTimeField()
27 | author = models.CharField(max_length=50)
28 | num = models.CharField(max_length=50, default='0')
29 | duration = models.CharField(max_length=50,default='0')
30 | status = models.CharField(max_length=50, default='done')
31 | result = models.CharField(max_length=50, default='FAILED')
32 | deleted = models.IntegerField(default=0)
33 | version = models.IntegerField(default='10000000')
34 |
35 |
36 | # 用例版本号信息
37 | class Case_Version_Info(models.Model):
38 | case_name = models.TextField(max_length=200) # 用例名,.py文件
39 | latest_version = models.IntegerField(default=10000000) # 版本号 八位
40 | update_time = models.DateTimeField(default=timezone.now)
41 |
42 |
43 | # 运行记录
44 | class Case_Save_Info(models.Model):
45 | case_name = models.TextField(max_length=200) # 用例名+方法
46 | version = models.IntegerField(default=10000000)
47 | author = models.CharField(max_length=50)
48 | save_time = models.DateTimeField(default=timezone.now)
49 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/routing.py:
--------------------------------------------------------------------------------
1 | from channels.routing import route, include
2 |
3 | from .core import consumers
4 | from .core.routing import case_manager_routing
5 |
6 | routing = [
7 | # You can use a string import path as the first argument as well.
8 | include(case_manager_routing, path=r"^/arbiter"),
9 | ]
--------------------------------------------------------------------------------
/arbiter-web/arbiter/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for arbiter project.
3 |
4 | Generated by 'django-admin startproject' using Django 1.11.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/1.11/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/1.11/ref/settings/
11 | """
12 |
13 | import os
14 | import datetime
15 | import redis
16 | from psycopg2.pool import ThreadedConnectionPool
17 | from config import arbiter_prod_config as env_config
18 |
19 | # mongodb_host = env_config['mongodb_host']
20 | # mongodb_port = env_config['mongodb_port']
21 | elk_url = env_config['elk_url']
22 | redis_host = env_config['redis_host']
23 | redis_port = env_config['redis_port']
24 | redis_dj_db = env_config['redis_dj_db']
25 | redis_arbiter_db = env_config['redis_arbiter_db']
26 | redis_elk_db = env_config['redis_elk_db']
27 | redis_url = 'redis://' + redis_host + ':' + str(redis_port) + '/' + str(redis_dj_db)
28 | pgsql_host = env_config['pgsql_host']
29 | pgsql_port = env_config['pgsql_port']
30 | pgsql_user = env_config['pgsql_user']
31 | pgsql_password = env_config['pgsql_password']
32 | pgsql_dbname = env_config['pgsql_dbname']
33 | case_path = env_config['case_path']
34 | os.environ["CASEPATH"] = case_path
35 | os.putenv("CASEPATH", case_path)
36 | case_obj_name = case_path.split('/')[0]
37 | redis_arbiter_pool = redis.ConnectionPool(host=redis_host, decode_responses=True, port=redis_port, db=redis_arbiter_db)
38 | redis_elk_pool = redis.ConnectionPool(host=redis_host, port=redis_port, db=redis_elk_db)
39 | pgsql_pool = ThreadedConnectionPool(1, 10, port=pgsql_port, host=pgsql_host,dbname=pgsql_dbname, user=pgsql_user, password=pgsql_password)
40 |
41 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
42 | PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
43 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
44 | ARBITER_SHELL_ROOT = os.path.dirname(BASE_DIR)
45 |
46 | # Quick-start development settings - unsuitable for production
47 | # See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
48 |
49 | # SECURITY WARNING: keep the secret key used in production secret!
50 | SECRET_KEY = '4d*!@um+nv9-lx#k215nrr=6oijv-l&)sdn585_bjzlljlmszg'
51 |
52 | # SECURITY WARNING: don't run with debug turned on in production!
53 | DEBUG = True
54 | APPEND_SLASH = False
55 | PREPEND_WWW = False
56 | ALLOWED_HOSTS = ['*']
57 |
58 | CHANNEL_LAYERS = {
59 | "default": {
60 | "BACKEND": "asgi_redis.RedisChannelLayer",
61 | "ROUTING": "arbiter.routing.routing",
62 | "CONFIG": {
63 | "hosts": [redis_url],
64 | "symmetric_encryption_keys": [SECRET_KEY],
65 | },
66 | },
67 | }
68 |
69 | # Application definition
70 |
71 | INSTALLED_APPS = [
72 | 'django.contrib.admin',
73 | 'django.contrib.auth',
74 | 'django.contrib.contenttypes',
75 | 'django.contrib.sessions',
76 | 'django.contrib.messages',
77 | 'django.contrib.staticfiles',
78 | 'channels',
79 | 'arbiter',
80 | 'arbiter.core',
81 | 'arbiter.wholog'
82 | ]
83 |
84 | MIDDLEWARE = [
85 | 'django.middleware.security.SecurityMiddleware',
86 | 'django.contrib.sessions.middleware.SessionMiddleware',
87 | 'django.middleware.common.CommonMiddleware',
88 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
89 | 'django.contrib.messages.middleware.MessageMiddleware',
90 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
91 | ]
92 |
93 | ROOT_URLCONF = 'arbiter.urls'
94 |
95 | TEMPLATES = [
96 | {
97 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
98 | 'DIRS': [
99 | os.path.join(PROJECT_ROOT, 'templates'),
100 | ],
101 | 'APP_DIRS': True,
102 | 'OPTIONS': {
103 | 'context_processors': [
104 | 'django.template.context_processors.debug',
105 | 'django.template.context_processors.request',
106 | 'django.contrib.auth.context_processors.auth',
107 | 'django.contrib.messages.context_processors.messages',
108 | ],
109 | },
110 | },
111 | ]
112 |
113 | WSGI_APPLICATION = 'arbiter.wsgi.application'
114 |
115 | # Rest framework
116 | REST_FRAMEWORK = {
117 | 'DEFAULT_PERMISSION_CLASSES': (
118 | 'rest_framework.permissions.IsAuthenticated',
119 | ),
120 | 'DEFAULT_AUTHENTICATION_CLASSES': (
121 | 'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
122 | 'rest_framework.authentication.SessionAuthentication',
123 | 'rest_framework.authentication.BasicAuthentication',
124 | ),
125 | }
126 |
127 | # jwt
128 | JWT_AUTH = {
129 | 'JWT_ENCODE_HANDLER':
130 | 'rest_framework_jwt.utils.jwt_encode_handler',
131 |
132 | 'JWT_DECODE_HANDLER':
133 | 'rest_framework_jwt.utils.jwt_decode_handler',
134 |
135 | 'JWT_PAYLOAD_HANDLER':
136 | 'rest_framework_jwt.utils.jwt_payload_handler',
137 |
138 | 'JWT_PAYLOAD_GET_USER_ID_HANDLER':
139 | 'rest_framework_jwt.utils.jwt_get_user_id_from_payload_handler',
140 |
141 | 'JWT_RESPONSE_PAYLOAD_HANDLER':
142 | 'rest_framework_jwt.utils.jwt_response_payload_handler',
143 |
144 | # 'JWT_SECRET_KEY': settings.SECRET_KEY,
145 | 'JWT_GET_USER_SECRET_KEY': None,
146 | 'JWT_PUBLIC_KEY': None,
147 | 'JWT_PRIVATE_KEY': None,
148 | 'JWT_ALGORITHM': 'HS256',
149 | 'JWT_VERIFY': True,
150 | 'JWT_VERIFY_EXPIRATION': True,
151 | 'JWT_LEEWAY': 0,
152 | 'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=3000),
153 | 'JWT_AUDIENCE': None,
154 | 'JWT_ISSUER': None,
155 |
156 | 'JWT_ALLOW_REFRESH': False,
157 | 'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),
158 |
159 | 'JWT_AUTH_HEADER_PREFIX': 'JWT',
160 | 'JWT_AUTH_COOKIE': None,
161 |
162 | }
163 |
164 | # Database
165 | # https://docs.djangoproject.com/en/1.11/ref/settings/#databases
166 |
167 | DATABASES = {
168 | 'default': {
169 | 'ENGINE': 'django.db.backends.postgresql',
170 | 'NAME': 'arbiter_dj',
171 | 'USER': 'luna', # 你的数据库用户名
172 | 'PASSWORD': 'luna', # 你的数据库密码
173 | 'HOST': pgsql_host, # 你的数据库主机,留空默认为localhost
174 | 'PORT': pgsql_port, # 你的数据库端口
175 | 'OPTIONS': {
176 | 'client_encoding': 'utf8',
177 | },
178 | }
179 | }
180 | # AUTHENTICATION_BACKENDS = ('mongoengine.django.auth.MongoEngineBackend',)
181 | # Password validation
182 | # https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
183 |
184 | AUTH_PASSWORD_VALIDATORS = [
185 | {
186 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
187 | },
188 | {
189 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
190 | },
191 | {
192 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
193 | },
194 | {
195 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
196 | },
197 | ]
198 |
199 | # Internationalization
200 | # https://docs.djangoproject.com/en/1.11/topics/i18n/
201 |
202 | LANGUAGE_CODE = 'en-us'
203 |
204 | TIME_ZONE = 'UTC'
205 |
206 | USE_I18N = True
207 |
208 | USE_L10N = True
209 |
210 | # 09-11 为支持create_time查询排序修改为true
211 | USE_TZ = True
212 |
213 | # Static files (CSS, JavaScript, Images)
214 | # https://docs.djangoproject.com/en/1.11/howto/static-files/
215 | # STATIC_ROOT = os.path.join(ARBITER_SHELL_ROOT, "shell")
216 | STATIC_URL = '/static/'
217 |
218 | STATICFILES_DIRS = [
219 | os.path.join(PROJECT_ROOT, "static"), os.path.join(ARBITER_SHELL_ROOT, "arbiter-cases/" + case_obj_name),
220 | ]
221 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/css/datatables/dataTables.bootstrap.css:
--------------------------------------------------------------------------------
1 | table.dataTable {
2 | clear: both;
3 | margin-top: 6px !important;
4 | margin-bottom: 6px !important;
5 | max-width: none !important;
6 | border-collapse: separate !important;
7 | }
8 | table.dataTable td,
9 | table.dataTable th {
10 | -webkit-box-sizing: content-box;
11 | box-sizing: content-box;
12 | }
13 | table.dataTable td.dataTables_empty,
14 | table.dataTable th.dataTables_empty {
15 | text-align: center;
16 | }
17 | table.dataTable.nowrap th,
18 | table.dataTable.nowrap td {
19 | white-space: nowrap;
20 | }
21 |
22 | div.dataTables_wrapper div.dataTables_length label {
23 | font-weight: normal;
24 | text-align: left;
25 | white-space: nowrap;
26 | }
27 | div.dataTables_wrapper div.dataTables_length select {
28 | width: 75px;
29 | display: inline-block;
30 | }
31 | div.dataTables_wrapper div.dataTables_filter {
32 | text-align: right;
33 | }
34 | div.dataTables_wrapper div.dataTables_filter label {
35 | font-weight: normal;
36 | white-space: nowrap;
37 | text-align: left;
38 | }
39 | div.dataTables_wrapper div.dataTables_filter input {
40 | margin-left: 0.5em;
41 | display: inline-block;
42 | width: auto;
43 | }
44 | div.dataTables_wrapper div.dataTables_info {
45 | padding-top: 8px;
46 | white-space: nowrap;
47 | }
48 | div.dataTables_wrapper div.dataTables_paginate {
49 | margin: 0;
50 | white-space: nowrap;
51 | text-align: right;
52 | }
53 | div.dataTables_wrapper div.dataTables_paginate ul.pagination {
54 | margin: 2px 0;
55 | white-space: nowrap;
56 | }
57 | div.dataTables_wrapper div.dataTables_processing {
58 | position: absolute;
59 | top: 50%;
60 | left: 50%;
61 | width: 200px;
62 | margin-left: -100px;
63 | margin-top: -26px;
64 | text-align: center;
65 | padding: 1em 0;
66 | }
67 |
68 | table.dataTable thead > tr > th.sorting_asc, table.dataTable thead > tr > th.sorting_desc, table.dataTable thead > tr > th.sorting,
69 | table.dataTable thead > tr > td.sorting_asc,
70 | table.dataTable thead > tr > td.sorting_desc,
71 | table.dataTable thead > tr > td.sorting {
72 | padding-right: 30px;
73 | }
74 | table.dataTable thead > tr > th:active,
75 | table.dataTable thead > tr > td:active {
76 | outline: none;
77 | }
78 | table.dataTable thead .sorting,
79 | table.dataTable thead .sorting_asc,
80 | table.dataTable thead .sorting_desc,
81 | table.dataTable thead .sorting_asc_disabled,
82 | table.dataTable thead .sorting_desc_disabled {
83 | cursor: pointer;
84 | position: relative;
85 | }
86 | table.dataTable thead .sorting:after,
87 | table.dataTable thead .sorting_asc:after,
88 | table.dataTable thead .sorting_desc:after,
89 | table.dataTable thead .sorting_asc_disabled:after,
90 | table.dataTable thead .sorting_desc_disabled:after {
91 | position: absolute;
92 | bottom: 8px;
93 | right: 8px;
94 | display: block;
95 | font-family: 'Glyphicons Halflings';
96 | opacity: 0.5;
97 | }
98 | table.dataTable thead .sorting:after {
99 | opacity: 0.2;
100 | content: "\e150";
101 | /* sort */
102 | }
103 | table.dataTable thead .sorting_asc:after {
104 | content: "\e155";
105 | /* sort-by-attributes */
106 | }
107 | table.dataTable thead .sorting_desc:after {
108 | content: "\e156";
109 | /* sort-by-attributes-alt */
110 | }
111 | table.dataTable thead .sorting_asc_disabled:after,
112 | table.dataTable thead .sorting_desc_disabled:after {
113 | color: #eee;
114 | }
115 |
116 | div.dataTables_scrollHead table.dataTable {
117 | margin-bottom: 0 !important;
118 | }
119 |
120 | div.dataTables_scrollBody > table {
121 | border-top: none;
122 | margin-top: 0 !important;
123 | margin-bottom: 0 !important;
124 | }
125 | div.dataTables_scrollBody > table > thead .sorting:after,
126 | div.dataTables_scrollBody > table > thead .sorting_asc:after,
127 | div.dataTables_scrollBody > table > thead .sorting_desc:after {
128 | display: none;
129 | }
130 | div.dataTables_scrollBody > table > tbody > tr:first-child > th,
131 | div.dataTables_scrollBody > table > tbody > tr:first-child > td {
132 | border-top: none;
133 | }
134 |
135 | div.dataTables_scrollFoot > table {
136 | margin-top: 0 !important;
137 | border-top: none;
138 | }
139 |
140 | @media screen and (max-width: 767px) {
141 | div.dataTables_wrapper div.dataTables_length,
142 | div.dataTables_wrapper div.dataTables_filter,
143 | div.dataTables_wrapper div.dataTables_info,
144 | div.dataTables_wrapper div.dataTables_paginate {
145 | text-align: center;
146 | }
147 | }
148 | table.dataTable.table-condensed > thead > tr > th {
149 | padding-right: 20px;
150 | }
151 | table.dataTable.table-condensed .sorting:after,
152 | table.dataTable.table-condensed .sorting_asc:after,
153 | table.dataTable.table-condensed .sorting_desc:after {
154 | top: 6px;
155 | right: 6px;
156 | }
157 |
158 | table.table-bordered.dataTable th,
159 | table.table-bordered.dataTable td {
160 | border-left-width: 0;
161 | }
162 | table.table-bordered.dataTable th:last-child, table.table-bordered.dataTable th:last-child,
163 | table.table-bordered.dataTable td:last-child,
164 | table.table-bordered.dataTable td:last-child {
165 | border-right-width: 0;
166 | }
167 | table.table-bordered.dataTable tbody th,
168 | table.table-bordered.dataTable tbody td {
169 | border-bottom-width: 0;
170 | }
171 |
172 | div.dataTables_scrollHead table.table-bordered {
173 | border-bottom-width: 0;
174 | }
175 |
176 | div.table-responsive > div.dataTables_wrapper > div.row {
177 | margin: 0;
178 | }
179 | div.table-responsive > div.dataTables_wrapper > div.row > div[class^="col-"]:first-child {
180 | padding-left: 0;
181 | }
182 | div.table-responsive > div.dataTables_wrapper > div.row > div[class^="col-"]:last-child {
183 | padding-right: 0;
184 | }
185 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/css/datatables/dataTables.bootstrap.min.css:
--------------------------------------------------------------------------------
1 | table.dataTable{clear:both;margin-top:6px !important;margin-bottom:6px !important;max-width:none !important;border-collapse:separate !important}table.dataTable td,table.dataTable th{-webkit-box-sizing:content-box;box-sizing:content-box}table.dataTable td.dataTables_empty,table.dataTable th.dataTables_empty{text-align:center}table.dataTable.nowrap th,table.dataTable.nowrap td{white-space:nowrap}div.dataTables_wrapper div.dataTables_length label{font-weight:normal;text-align:left;white-space:nowrap}div.dataTables_wrapper div.dataTables_length select{width:75px;display:inline-block}div.dataTables_wrapper div.dataTables_filter{text-align:right}div.dataTables_wrapper div.dataTables_filter label{font-weight:normal;white-space:nowrap;text-align:left}div.dataTables_wrapper div.dataTables_filter input{margin-left:0.5em;display:inline-block;width:auto}div.dataTables_wrapper div.dataTables_info{padding-top:8px;white-space:nowrap}div.dataTables_wrapper div.dataTables_paginate{margin:0;white-space:nowrap;text-align:right}div.dataTables_wrapper div.dataTables_paginate ul.pagination{margin:2px 0;white-space:nowrap}div.dataTables_wrapper div.dataTables_processing{position:absolute;top:50%;left:50%;width:200px;margin-left:-100px;margin-top:-26px;text-align:center;padding:1em 0}table.dataTable thead>tr>th.sorting_asc,table.dataTable thead>tr>th.sorting_desc,table.dataTable thead>tr>th.sorting,table.dataTable thead>tr>td.sorting_asc,table.dataTable thead>tr>td.sorting_desc,table.dataTable thead>tr>td.sorting{padding-right:30px}table.dataTable thead>tr>th:active,table.dataTable thead>tr>td:active{outline:none}table.dataTable thead .sorting,table.dataTable thead .sorting_asc,table.dataTable thead .sorting_desc,table.dataTable thead .sorting_asc_disabled,table.dataTable thead .sorting_desc_disabled{cursor:pointer;position:relative}table.dataTable thead .sorting:after,table.dataTable thead .sorting_asc:after,table.dataTable thead .sorting_desc:after,table.dataTable thead .sorting_asc_disabled:after,table.dataTable thead .sorting_desc_disabled:after{position:absolute;bottom:8px;right:8px;display:block;font-family:'Glyphicons Halflings';opacity:0.5}table.dataTable thead .sorting:after{opacity:0.2;content:"\e150"}table.dataTable thead .sorting_asc:after{content:"\e155"}table.dataTable thead .sorting_desc:after{content:"\e156"}table.dataTable thead .sorting_asc_disabled:after,table.dataTable thead .sorting_desc_disabled:after{color:#eee}div.dataTables_scrollHead table.dataTable{margin-bottom:0 !important}div.dataTables_scrollBody>table{border-top:none;margin-top:0 !important;margin-bottom:0 !important}div.dataTables_scrollBody>table>thead .sorting:after,div.dataTables_scrollBody>table>thead .sorting_asc:after,div.dataTables_scrollBody>table>thead .sorting_desc:after{display:none}div.dataTables_scrollBody>table>tbody>tr:first-child>th,div.dataTables_scrollBody>table>tbody>tr:first-child>td{border-top:none}div.dataTables_scrollFoot>table{margin-top:0 !important;border-top:none}@media screen and (max-width: 767px){div.dataTables_wrapper div.dataTables_length,div.dataTables_wrapper div.dataTables_filter,div.dataTables_wrapper div.dataTables_info,div.dataTables_wrapper div.dataTables_paginate{text-align:center}}table.dataTable.table-condensed>thead>tr>th{padding-right:20px}table.dataTable.table-condensed .sorting:after,table.dataTable.table-condensed .sorting_asc:after,table.dataTable.table-condensed .sorting_desc:after{top:6px;right:6px}table.table-bordered.dataTable th,table.table-bordered.dataTable td{border-left-width:0}table.table-bordered.dataTable th:last-child,table.table-bordered.dataTable th:last-child,table.table-bordered.dataTable td:last-child,table.table-bordered.dataTable td:last-child{border-right-width:0}table.table-bordered.dataTable tbody th,table.table-bordered.dataTable tbody td{border-bottom-width:0}div.dataTables_scrollHead table.table-bordered{border-bottom-width:0}div.table-responsive>div.dataTables_wrapper>div.row{margin:0}div.table-responsive>div.dataTables_wrapper>div.row>div[class^="col-"]:first-child{padding-left:0}div.table-responsive>div.dataTables_wrapper>div.row>div[class^="col-"]:last-child{padding-right:0}
2 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/css/datatables/dataTables.bootstrap4.css:
--------------------------------------------------------------------------------
1 | table.dataTable {
2 | clear: both;
3 | margin-top: 6px !important;
4 | margin-bottom: 6px !important;
5 | max-width: none !important;
6 | border-collapse: separate !important;
7 | }
8 | table.dataTable td,
9 | table.dataTable th {
10 | -webkit-box-sizing: content-box;
11 | box-sizing: content-box;
12 | }
13 | table.dataTable td.dataTables_empty,
14 | table.dataTable th.dataTables_empty {
15 | text-align: center;
16 | }
17 | table.dataTable.nowrap th,
18 | table.dataTable.nowrap td {
19 | white-space: nowrap;
20 | }
21 |
22 | div.dataTables_wrapper div.dataTables_length label {
23 | font-weight: normal;
24 | text-align: left;
25 | white-space: nowrap;
26 | }
27 | div.dataTables_wrapper div.dataTables_length select {
28 | width: 75px;
29 | display: inline-block;
30 | }
31 | div.dataTables_wrapper div.dataTables_filter {
32 | text-align: right;
33 | }
34 | div.dataTables_wrapper div.dataTables_filter label {
35 | font-weight: normal;
36 | white-space: nowrap;
37 | text-align: left;
38 | }
39 | div.dataTables_wrapper div.dataTables_filter input {
40 | margin-left: 0.5em;
41 | display: inline-block;
42 | width: auto;
43 | }
44 | div.dataTables_wrapper div.dataTables_info {
45 | padding-top: 0.85em;
46 | white-space: nowrap;
47 | }
48 | div.dataTables_wrapper div.dataTables_paginate {
49 | margin: 0;
50 | white-space: nowrap;
51 | text-align: right;
52 | }
53 | div.dataTables_wrapper div.dataTables_paginate ul.pagination {
54 | margin: 2px 0;
55 | white-space: nowrap;
56 | justify-content: flex-end;
57 | }
58 | div.dataTables_wrapper div.dataTables_processing {
59 | position: absolute;
60 | top: 50%;
61 | left: 50%;
62 | width: 200px;
63 | margin-left: -100px;
64 | margin-top: -26px;
65 | text-align: center;
66 | padding: 1em 0;
67 | }
68 |
69 | table.dataTable thead > tr > th.sorting_asc, table.dataTable thead > tr > th.sorting_desc, table.dataTable thead > tr > th.sorting,
70 | table.dataTable thead > tr > td.sorting_asc,
71 | table.dataTable thead > tr > td.sorting_desc,
72 | table.dataTable thead > tr > td.sorting {
73 | padding-right: 30px;
74 | }
75 | table.dataTable thead > tr > th:active,
76 | table.dataTable thead > tr > td:active {
77 | outline: none;
78 | }
79 | table.dataTable thead .sorting,
80 | table.dataTable thead .sorting_asc,
81 | table.dataTable thead .sorting_desc,
82 | table.dataTable thead .sorting_asc_disabled,
83 | table.dataTable thead .sorting_desc_disabled {
84 | cursor: pointer;
85 | position: relative;
86 | }
87 | table.dataTable thead .sorting:before, table.dataTable thead .sorting:after,
88 | table.dataTable thead .sorting_asc:before,
89 | table.dataTable thead .sorting_asc:after,
90 | table.dataTable thead .sorting_desc:before,
91 | table.dataTable thead .sorting_desc:after,
92 | table.dataTable thead .sorting_asc_disabled:before,
93 | table.dataTable thead .sorting_asc_disabled:after,
94 | table.dataTable thead .sorting_desc_disabled:before,
95 | table.dataTable thead .sorting_desc_disabled:after {
96 | position: absolute;
97 | bottom: 0.9em;
98 | display: block;
99 | opacity: 0.3;
100 | }
101 | table.dataTable thead .sorting:before,
102 | table.dataTable thead .sorting_asc:before,
103 | table.dataTable thead .sorting_desc:before,
104 | table.dataTable thead .sorting_asc_disabled:before,
105 | table.dataTable thead .sorting_desc_disabled:before {
106 | right: 1em;
107 | content: "\2191";
108 | }
109 | table.dataTable thead .sorting:after,
110 | table.dataTable thead .sorting_asc:after,
111 | table.dataTable thead .sorting_desc:after,
112 | table.dataTable thead .sorting_asc_disabled:after,
113 | table.dataTable thead .sorting_desc_disabled:after {
114 | right: 0.5em;
115 | content: "\2193";
116 | }
117 | table.dataTable thead .sorting_asc:before,
118 | table.dataTable thead .sorting_desc:after {
119 | opacity: 1;
120 | }
121 | table.dataTable thead .sorting_asc_disabled:before,
122 | table.dataTable thead .sorting_desc_disabled:after {
123 | opacity: 0;
124 | }
125 |
126 | div.dataTables_scrollHead table.dataTable {
127 | margin-bottom: 0 !important;
128 | }
129 |
130 | div.dataTables_scrollBody table {
131 | border-top: none;
132 | margin-top: 0 !important;
133 | margin-bottom: 0 !important;
134 | }
135 | div.dataTables_scrollBody table thead .sorting:after,
136 | div.dataTables_scrollBody table thead .sorting_asc:after,
137 | div.dataTables_scrollBody table thead .sorting_desc:after {
138 | display: none;
139 | }
140 | div.dataTables_scrollBody table tbody tr:first-child th,
141 | div.dataTables_scrollBody table tbody tr:first-child td {
142 | border-top: none;
143 | }
144 |
145 | div.dataTables_scrollFoot table {
146 | margin-top: 0 !important;
147 | border-top: none;
148 | }
149 |
150 | @media screen and (max-width: 767px) {
151 | div.dataTables_wrapper div.dataTables_length,
152 | div.dataTables_wrapper div.dataTables_filter,
153 | div.dataTables_wrapper div.dataTables_info,
154 | div.dataTables_wrapper div.dataTables_paginate {
155 | text-align: center;
156 | }
157 | }
158 | table.dataTable.table-condensed > thead > tr > th {
159 | padding-right: 20px;
160 | }
161 | table.dataTable.table-condensed .sorting:after,
162 | table.dataTable.table-condensed .sorting_asc:after,
163 | table.dataTable.table-condensed .sorting_desc:after {
164 | top: 6px;
165 | right: 6px;
166 | }
167 |
168 | table.table-bordered.dataTable th,
169 | table.table-bordered.dataTable td {
170 | border-left-width: 0;
171 | }
172 | table.table-bordered.dataTable th:last-child, table.table-bordered.dataTable th:last-child,
173 | table.table-bordered.dataTable td:last-child,
174 | table.table-bordered.dataTable td:last-child {
175 | border-right-width: 0;
176 | }
177 | table.table-bordered.dataTable tbody th,
178 | table.table-bordered.dataTable tbody td {
179 | border-bottom-width: 0;
180 | }
181 |
182 | div.dataTables_scrollHead table.table-bordered {
183 | border-bottom-width: 0;
184 | }
185 |
186 | div.table-responsive > div.dataTables_wrapper > div.row {
187 | margin: 0;
188 | }
189 | div.table-responsive > div.dataTables_wrapper > div.row > div[class^="col-"]:first-child {
190 | padding-left: 0;
191 | }
192 | div.table-responsive > div.dataTables_wrapper > div.row > div[class^="col-"]:last-child {
193 | padding-right: 0;
194 | }
195 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/css/datatables/dataTables.bootstrap4.min.css:
--------------------------------------------------------------------------------
1 | table.dataTable{clear:both;margin-top:6px !important;margin-bottom:6px !important;max-width:none !important;border-collapse:separate !important}table.dataTable td,table.dataTable th{-webkit-box-sizing:content-box;box-sizing:content-box}table.dataTable td.dataTables_empty,table.dataTable th.dataTables_empty{text-align:center}table.dataTable.nowrap th,table.dataTable.nowrap td{white-space:nowrap}div.dataTables_wrapper div.dataTables_length label{font-weight:normal;text-align:left;white-space:nowrap}div.dataTables_wrapper div.dataTables_length select{width:75px;display:inline-block}div.dataTables_wrapper div.dataTables_filter{text-align:right}div.dataTables_wrapper div.dataTables_filter label{font-weight:normal;white-space:nowrap;text-align:left}div.dataTables_wrapper div.dataTables_filter input{margin-left:0.5em;display:inline-block;width:auto}div.dataTables_wrapper div.dataTables_info{padding-top:0.85em;white-space:nowrap}div.dataTables_wrapper div.dataTables_paginate{margin:0;white-space:nowrap;text-align:right}div.dataTables_wrapper div.dataTables_paginate ul.pagination{margin:2px 0;white-space:nowrap;justify-content:flex-end}div.dataTables_wrapper div.dataTables_processing{position:absolute;top:50%;left:50%;width:200px;margin-left:-100px;margin-top:-26px;text-align:center;padding:1em 0}table.dataTable thead>tr>th.sorting_asc,table.dataTable thead>tr>th.sorting_desc,table.dataTable thead>tr>th.sorting,table.dataTable thead>tr>td.sorting_asc,table.dataTable thead>tr>td.sorting_desc,table.dataTable thead>tr>td.sorting{padding-right:30px}table.dataTable thead>tr>th:active,table.dataTable thead>tr>td:active{outline:none}table.dataTable thead .sorting,table.dataTable thead .sorting_asc,table.dataTable thead .sorting_desc,table.dataTable thead .sorting_asc_disabled,table.dataTable thead .sorting_desc_disabled{cursor:pointer;position:relative}table.dataTable thead .sorting:before,table.dataTable thead .sorting:after,table.dataTable thead .sorting_asc:before,table.dataTable thead .sorting_asc:after,table.dataTable thead .sorting_desc:before,table.dataTable thead .sorting_desc:after,table.dataTable thead .sorting_asc_disabled:before,table.dataTable thead .sorting_asc_disabled:after,table.dataTable thead .sorting_desc_disabled:before,table.dataTable thead .sorting_desc_disabled:after{position:absolute;bottom:0.9em;display:block;opacity:0.3}table.dataTable thead .sorting:before,table.dataTable thead .sorting_asc:before,table.dataTable thead .sorting_desc:before,table.dataTable thead .sorting_asc_disabled:before,table.dataTable thead .sorting_desc_disabled:before{right:1em;content:"\2191"}table.dataTable thead .sorting:after,table.dataTable thead .sorting_asc:after,table.dataTable thead .sorting_desc:after,table.dataTable thead .sorting_asc_disabled:after,table.dataTable thead .sorting_desc_disabled:after{right:0.5em;content:"\2193"}table.dataTable thead .sorting_asc:before,table.dataTable thead .sorting_desc:after{opacity:1}table.dataTable thead .sorting_asc_disabled:before,table.dataTable thead .sorting_desc_disabled:after{opacity:0}div.dataTables_scrollHead table.dataTable{margin-bottom:0 !important}div.dataTables_scrollBody table{border-top:none;margin-top:0 !important;margin-bottom:0 !important}div.dataTables_scrollBody table thead .sorting:after,div.dataTables_scrollBody table thead .sorting_asc:after,div.dataTables_scrollBody table thead .sorting_desc:after{display:none}div.dataTables_scrollBody table tbody tr:first-child th,div.dataTables_scrollBody table tbody tr:first-child td{border-top:none}div.dataTables_scrollFoot table{margin-top:0 !important;border-top:none}@media screen and (max-width: 767px){div.dataTables_wrapper div.dataTables_length,div.dataTables_wrapper div.dataTables_filter,div.dataTables_wrapper div.dataTables_info,div.dataTables_wrapper div.dataTables_paginate{text-align:center}}table.dataTable.table-condensed>thead>tr>th{padding-right:20px}table.dataTable.table-condensed .sorting:after,table.dataTable.table-condensed .sorting_asc:after,table.dataTable.table-condensed .sorting_desc:after{top:6px;right:6px}table.table-bordered.dataTable th,table.table-bordered.dataTable td{border-left-width:0}table.table-bordered.dataTable th:last-child,table.table-bordered.dataTable th:last-child,table.table-bordered.dataTable td:last-child,table.table-bordered.dataTable td:last-child{border-right-width:0}table.table-bordered.dataTable tbody th,table.table-bordered.dataTable tbody td{border-bottom-width:0}div.dataTables_scrollHead table.table-bordered{border-bottom-width:0}div.table-responsive>div.dataTables_wrapper>div.row{margin:0}div.table-responsive>div.dataTables_wrapper>div.row>div[class^="col-"]:first-child{padding-left:0}div.table-responsive>div.dataTables_wrapper>div.row>div[class^="col-"]:last-child{padding-right:0}
2 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/css/datatables/dataTables.foundation.css:
--------------------------------------------------------------------------------
1 | table.dataTable {
2 | clear: both;
3 | margin: 0.5em 0 !important;
4 | max-width: none !important;
5 | width: 100%;
6 | }
7 | table.dataTable td,
8 | table.dataTable th {
9 | -webkit-box-sizing: content-box;
10 | box-sizing: content-box;
11 | }
12 | table.dataTable td.dataTables_empty,
13 | table.dataTable th.dataTables_empty {
14 | text-align: center;
15 | }
16 | table.dataTable.nowrap th, table.dataTable.nowrap td {
17 | white-space: nowrap;
18 | }
19 |
20 | div.dataTables_wrapper {
21 | position: relative;
22 | }
23 | div.dataTables_wrapper div.dataTables_length label {
24 | float: left;
25 | text-align: left;
26 | margin-bottom: 0;
27 | }
28 | div.dataTables_wrapper div.dataTables_length select {
29 | width: 75px;
30 | margin-bottom: 0;
31 | }
32 | div.dataTables_wrapper div.dataTables_filter label {
33 | float: right;
34 | margin-bottom: 0;
35 | }
36 | div.dataTables_wrapper div.dataTables_filter input {
37 | display: inline-block !important;
38 | width: auto !important;
39 | margin-bottom: 0;
40 | margin-left: 0.5em;
41 | }
42 | div.dataTables_wrapper div.dataTables_info {
43 | padding-top: 2px;
44 | }
45 | div.dataTables_wrapper div.dataTables_paginate {
46 | float: right;
47 | margin: 0;
48 | }
49 | div.dataTables_wrapper div.dataTables_processing {
50 | position: absolute;
51 | top: 50%;
52 | left: 50%;
53 | width: 200px;
54 | margin-left: -100px;
55 | margin-top: -26px;
56 | text-align: center;
57 | padding: 1rem 0;
58 | }
59 |
60 | table.dataTable thead > tr > th.sorting_asc, table.dataTable thead > tr > th.sorting_desc, table.dataTable thead > tr > th.sorting,
61 | table.dataTable thead > tr > td.sorting_asc,
62 | table.dataTable thead > tr > td.sorting_desc,
63 | table.dataTable thead > tr > td.sorting {
64 | padding-right: 1.5rem;
65 | }
66 | table.dataTable thead > tr > th:active,
67 | table.dataTable thead > tr > td:active {
68 | outline: none;
69 | }
70 | table.dataTable thead .sorting,
71 | table.dataTable thead .sorting_asc,
72 | table.dataTable thead .sorting_desc,
73 | table.dataTable thead .sorting_asc_disabled,
74 | table.dataTable thead .sorting_desc_disabled {
75 | cursor: pointer;
76 | }
77 | table.dataTable thead .sorting,
78 | table.dataTable thead .sorting_asc,
79 | table.dataTable thead .sorting_desc,
80 | table.dataTable thead .sorting_asc_disabled,
81 | table.dataTable thead .sorting_desc_disabled {
82 | background-repeat: no-repeat;
83 | background-position: center right;
84 | }
85 | table.dataTable thead .sorting {
86 | background-image: url("../images/sort_both.png");
87 | }
88 | table.dataTable thead .sorting_asc {
89 | background-image: url("../images/sort_asc.png");
90 | }
91 | table.dataTable thead .sorting_desc {
92 | background-image: url("../images/sort_desc.png");
93 | }
94 | table.dataTable thead .sorting_asc_disabled {
95 | background-image: url("../images/sort_asc_disabled.png");
96 | }
97 | table.dataTable thead .sorting_desc_disabled {
98 | background-image: url("../images/sort_desc_disabled.png");
99 | }
100 |
101 | div.dataTables_scrollHead table {
102 | margin-bottom: 0 !important;
103 | }
104 |
105 | div.dataTables_scrollBody table {
106 | border-top: none;
107 | margin-top: 0 !important;
108 | margin-bottom: 0 !important;
109 | }
110 | div.dataTables_scrollBody table tbody tr:first-child th,
111 | div.dataTables_scrollBody table tbody tr:first-child td {
112 | border-top: none;
113 | }
114 |
115 | div.dataTables_scrollFoot table {
116 | margin-top: 0 !important;
117 | border-top: none;
118 | }
119 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/css/datatables/dataTables.foundation.min.css:
--------------------------------------------------------------------------------
1 | table.dataTable{clear:both;margin:0.5em 0 !important;max-width:none !important;width:100%}table.dataTable td,table.dataTable th{-webkit-box-sizing:content-box;box-sizing:content-box}table.dataTable td.dataTables_empty,table.dataTable th.dataTables_empty{text-align:center}table.dataTable.nowrap th,table.dataTable.nowrap td{white-space:nowrap}div.dataTables_wrapper{position:relative}div.dataTables_wrapper div.dataTables_length label{float:left;text-align:left;margin-bottom:0}div.dataTables_wrapper div.dataTables_length select{width:75px;margin-bottom:0}div.dataTables_wrapper div.dataTables_filter label{float:right;margin-bottom:0}div.dataTables_wrapper div.dataTables_filter input{display:inline-block !important;width:auto !important;margin-bottom:0;margin-left:0.5em}div.dataTables_wrapper div.dataTables_info{padding-top:2px}div.dataTables_wrapper div.dataTables_paginate{float:right;margin:0}div.dataTables_wrapper div.dataTables_processing{position:absolute;top:50%;left:50%;width:200px;margin-left:-100px;margin-top:-26px;text-align:center;padding:1rem 0}table.dataTable thead>tr>th.sorting_asc,table.dataTable thead>tr>th.sorting_desc,table.dataTable thead>tr>th.sorting,table.dataTable thead>tr>td.sorting_asc,table.dataTable thead>tr>td.sorting_desc,table.dataTable thead>tr>td.sorting{padding-right:1.5rem}table.dataTable thead>tr>th:active,table.dataTable thead>tr>td:active{outline:none}table.dataTable thead .sorting,table.dataTable thead .sorting_asc,table.dataTable thead .sorting_desc,table.dataTable thead .sorting_asc_disabled,table.dataTable thead .sorting_desc_disabled{cursor:pointer}table.dataTable thead .sorting,table.dataTable thead .sorting_asc,table.dataTable thead .sorting_desc,table.dataTable thead .sorting_asc_disabled,table.dataTable thead .sorting_desc_disabled{background-repeat:no-repeat;background-position:center right}table.dataTable thead .sorting{background-image:url("../images/sort_both.png")}table.dataTable thead .sorting_asc{background-image:url("../images/sort_asc.png")}table.dataTable thead .sorting_desc{background-image:url("../images/sort_desc.png")}table.dataTable thead .sorting_asc_disabled{background-image:url("../images/sort_asc_disabled.png")}table.dataTable thead .sorting_desc_disabled{background-image:url("../images/sort_desc_disabled.png")}div.dataTables_scrollHead table{margin-bottom:0 !important}div.dataTables_scrollBody table{border-top:none;margin-top:0 !important;margin-bottom:0 !important}div.dataTables_scrollBody table tbody tr:first-child th,div.dataTables_scrollBody table tbody tr:first-child td{border-top:none}div.dataTables_scrollFoot table{margin-top:0 !important;border-top:none}
2 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/css/datatables/dataTables.material.css:
--------------------------------------------------------------------------------
1 | div.dataTables_wrapper div.dataTables_filter {
2 | text-align: right;
3 | }
4 | div.dataTables_wrapper div.dataTables_filter input {
5 | margin-left: 0.5em;
6 | }
7 | div.dataTables_wrapper div.dataTables_info {
8 | padding-top: 10px;
9 | white-space: nowrap;
10 | }
11 | div.dataTables_wrapper div.dataTables_processing {
12 | position: absolute;
13 | top: 50%;
14 | left: 50%;
15 | width: 200px;
16 | margin-left: -100px;
17 | text-align: center;
18 | }
19 | div.dataTables_wrapper div.dataTables_paginate {
20 | text-align: right;
21 | }
22 | div.dataTables_wrapper div.mdl-grid.dt-table {
23 | padding-top: 0;
24 | padding-bottom: 0;
25 | }
26 | div.dataTables_wrapper div.mdl-grid.dt-table > div.mdl-cell {
27 | margin-top: 0;
28 | margin-bottom: 0;
29 | }
30 |
31 | table.dataTable thead > tr > th.sorting_asc, table.dataTable thead > tr > th.sorting_desc, table.dataTable thead > tr > th.sorting,
32 | table.dataTable thead > tr > td.sorting_asc,
33 | table.dataTable thead > tr > td.sorting_desc,
34 | table.dataTable thead > tr > td.sorting {
35 | padding-right: 30px;
36 | }
37 | table.dataTable thead > tr > th:active,
38 | table.dataTable thead > tr > td:active {
39 | outline: none;
40 | }
41 | table.dataTable thead .sorting,
42 | table.dataTable thead .sorting_asc,
43 | table.dataTable thead .sorting_desc,
44 | table.dataTable thead .sorting_asc_disabled,
45 | table.dataTable thead .sorting_desc_disabled {
46 | cursor: pointer;
47 | position: relative;
48 | }
49 | table.dataTable thead .sorting:before, table.dataTable thead .sorting:after,
50 | table.dataTable thead .sorting_asc:before,
51 | table.dataTable thead .sorting_asc:after,
52 | table.dataTable thead .sorting_desc:before,
53 | table.dataTable thead .sorting_desc:after,
54 | table.dataTable thead .sorting_asc_disabled:before,
55 | table.dataTable thead .sorting_asc_disabled:after,
56 | table.dataTable thead .sorting_desc_disabled:before,
57 | table.dataTable thead .sorting_desc_disabled:after {
58 | position: absolute;
59 | bottom: 11px;
60 | display: block;
61 | opacity: 0.3;
62 | font-size: 1.3em;
63 | }
64 | table.dataTable thead .sorting:before,
65 | table.dataTable thead .sorting_asc:before,
66 | table.dataTable thead .sorting_desc:before,
67 | table.dataTable thead .sorting_asc_disabled:before,
68 | table.dataTable thead .sorting_desc_disabled:before {
69 | right: 1em;
70 | content: "\2191";
71 | }
72 | table.dataTable thead .sorting:after,
73 | table.dataTable thead .sorting_asc:after,
74 | table.dataTable thead .sorting_desc:after,
75 | table.dataTable thead .sorting_asc_disabled:after,
76 | table.dataTable thead .sorting_desc_disabled:after {
77 | right: 0.5em;
78 | content: "\2193";
79 | }
80 | table.dataTable thead .sorting_asc:before,
81 | table.dataTable thead .sorting_desc:after {
82 | opacity: 1;
83 | }
84 | table.dataTable thead .sorting_asc_disabled:before,
85 | table.dataTable thead .sorting_desc_disabled:after {
86 | opacity: 0;
87 | }
88 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/css/datatables/dataTables.material.min.css:
--------------------------------------------------------------------------------
1 | div.dataTables_wrapper div.dataTables_filter{text-align:right}div.dataTables_wrapper div.dataTables_filter input{margin-left:0.5em}div.dataTables_wrapper div.dataTables_info{padding-top:10px;white-space:nowrap}div.dataTables_wrapper div.dataTables_processing{position:absolute;top:50%;left:50%;width:200px;margin-left:-100px;text-align:center}div.dataTables_wrapper div.dataTables_paginate{text-align:right}div.dataTables_wrapper div.mdl-grid.dt-table{padding-top:0;padding-bottom:0}div.dataTables_wrapper div.mdl-grid.dt-table>div.mdl-cell{margin-top:0;margin-bottom:0}table.dataTable thead>tr>th.sorting_asc,table.dataTable thead>tr>th.sorting_desc,table.dataTable thead>tr>th.sorting,table.dataTable thead>tr>td.sorting_asc,table.dataTable thead>tr>td.sorting_desc,table.dataTable thead>tr>td.sorting{padding-right:30px}table.dataTable thead>tr>th:active,table.dataTable thead>tr>td:active{outline:none}table.dataTable thead .sorting,table.dataTable thead .sorting_asc,table.dataTable thead .sorting_desc,table.dataTable thead .sorting_asc_disabled,table.dataTable thead .sorting_desc_disabled{cursor:pointer;position:relative}table.dataTable thead .sorting:before,table.dataTable thead .sorting:after,table.dataTable thead .sorting_asc:before,table.dataTable thead .sorting_asc:after,table.dataTable thead .sorting_desc:before,table.dataTable thead .sorting_desc:after,table.dataTable thead .sorting_asc_disabled:before,table.dataTable thead .sorting_asc_disabled:after,table.dataTable thead .sorting_desc_disabled:before,table.dataTable thead .sorting_desc_disabled:after{position:absolute;bottom:11px;display:block;opacity:0.3;font-size:1.3em}table.dataTable thead .sorting:before,table.dataTable thead .sorting_asc:before,table.dataTable thead .sorting_desc:before,table.dataTable thead .sorting_asc_disabled:before,table.dataTable thead .sorting_desc_disabled:before{right:1em;content:"\2191"}table.dataTable thead .sorting:after,table.dataTable thead .sorting_asc:after,table.dataTable thead .sorting_desc:after,table.dataTable thead .sorting_asc_disabled:after,table.dataTable thead .sorting_desc_disabled:after{right:0.5em;content:"\2193"}table.dataTable thead .sorting_asc:before,table.dataTable thead .sorting_desc:after{opacity:1}table.dataTable thead .sorting_asc_disabled:before,table.dataTable thead .sorting_desc_disabled:after{opacity:0}
2 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/css/datatables/dataTables.semanticui.css:
--------------------------------------------------------------------------------
1 | /*
2 | * Styling for DataTables with Semantic UI
3 | */
4 | table.dataTable.table {
5 | margin: 0;
6 | }
7 | table.dataTable.table thead th,
8 | table.dataTable.table thead td {
9 | position: relative;
10 | }
11 | table.dataTable.table thead th.sorting, table.dataTable.table thead th.sorting_asc, table.dataTable.table thead th.sorting_desc,
12 | table.dataTable.table thead td.sorting,
13 | table.dataTable.table thead td.sorting_asc,
14 | table.dataTable.table thead td.sorting_desc {
15 | padding-right: 20px;
16 | }
17 | table.dataTable.table thead th.sorting:after, table.dataTable.table thead th.sorting_asc:after, table.dataTable.table thead th.sorting_desc:after,
18 | table.dataTable.table thead td.sorting:after,
19 | table.dataTable.table thead td.sorting_asc:after,
20 | table.dataTable.table thead td.sorting_desc:after {
21 | position: absolute;
22 | top: 12px;
23 | right: 8px;
24 | display: block;
25 | font-family: Icons;
26 | }
27 | table.dataTable.table thead th.sorting:after,
28 | table.dataTable.table thead td.sorting:after {
29 | content: "\f0dc";
30 | color: #ddd;
31 | font-size: 0.8em;
32 | }
33 | table.dataTable.table thead th.sorting_asc:after,
34 | table.dataTable.table thead td.sorting_asc:after {
35 | content: "\f0de";
36 | }
37 | table.dataTable.table thead th.sorting_desc:after,
38 | table.dataTable.table thead td.sorting_desc:after {
39 | content: "\f0dd";
40 | }
41 | table.dataTable.table td,
42 | table.dataTable.table th {
43 | -webkit-box-sizing: content-box;
44 | box-sizing: content-box;
45 | }
46 | table.dataTable.table td.dataTables_empty,
47 | table.dataTable.table th.dataTables_empty {
48 | text-align: center;
49 | }
50 | table.dataTable.table.nowrap th,
51 | table.dataTable.table.nowrap td {
52 | white-space: nowrap;
53 | }
54 |
55 | div.dataTables_wrapper div.dataTables_length select {
56 | vertical-align: middle;
57 | min-height: 2.7142em;
58 | }
59 | div.dataTables_wrapper div.dataTables_length .ui.selection.dropdown {
60 | min-width: 0;
61 | }
62 | div.dataTables_wrapper div.dataTables_filter input {
63 | margin-left: 0.5em;
64 | }
65 | div.dataTables_wrapper div.dataTables_info {
66 | padding-top: 13px;
67 | white-space: nowrap;
68 | }
69 | div.dataTables_wrapper div.dataTables_processing {
70 | position: absolute;
71 | top: 50%;
72 | left: 50%;
73 | width: 200px;
74 | margin-left: -100px;
75 | text-align: center;
76 | }
77 | div.dataTables_wrapper div.row.dt-table {
78 | padding: 0;
79 | }
80 | div.dataTables_wrapper div.dataTables_scrollHead table.dataTable {
81 | border-bottom-right-radius: 0;
82 | border-bottom-left-radius: 0;
83 | border-bottom: none;
84 | }
85 | div.dataTables_wrapper div.dataTables_scrollBody thead .sorting:after,
86 | div.dataTables_wrapper div.dataTables_scrollBody thead .sorting_asc:after,
87 | div.dataTables_wrapper div.dataTables_scrollBody thead .sorting_desc:after {
88 | display: none;
89 | }
90 | div.dataTables_wrapper div.dataTables_scrollBody table.dataTable {
91 | border-radius: 0;
92 | border-top: none;
93 | border-bottom-width: 0;
94 | }
95 | div.dataTables_wrapper div.dataTables_scrollBody table.dataTable.no-footer {
96 | border-bottom-width: 1px;
97 | }
98 | div.dataTables_wrapper div.dataTables_scrollFoot table.dataTable {
99 | border-top-right-radius: 0;
100 | border-top-left-radius: 0;
101 | border-top: none;
102 | }
103 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/css/datatables/dataTables.semanticui.min.css:
--------------------------------------------------------------------------------
1 | table.dataTable.table{margin:0}table.dataTable.table thead th,table.dataTable.table thead td{position:relative}table.dataTable.table thead th.sorting,table.dataTable.table thead th.sorting_asc,table.dataTable.table thead th.sorting_desc,table.dataTable.table thead td.sorting,table.dataTable.table thead td.sorting_asc,table.dataTable.table thead td.sorting_desc{padding-right:20px}table.dataTable.table thead th.sorting:after,table.dataTable.table thead th.sorting_asc:after,table.dataTable.table thead th.sorting_desc:after,table.dataTable.table thead td.sorting:after,table.dataTable.table thead td.sorting_asc:after,table.dataTable.table thead td.sorting_desc:after{position:absolute;top:12px;right:8px;display:block;font-family:Icons}table.dataTable.table thead th.sorting:after,table.dataTable.table thead td.sorting:after{content:"\f0dc";color:#ddd;font-size:0.8em}table.dataTable.table thead th.sorting_asc:after,table.dataTable.table thead td.sorting_asc:after{content:"\f0de"}table.dataTable.table thead th.sorting_desc:after,table.dataTable.table thead td.sorting_desc:after{content:"\f0dd"}table.dataTable.table td,table.dataTable.table th{-webkit-box-sizing:content-box;box-sizing:content-box}table.dataTable.table td.dataTables_empty,table.dataTable.table th.dataTables_empty{text-align:center}table.dataTable.table.nowrap th,table.dataTable.table.nowrap td{white-space:nowrap}div.dataTables_wrapper div.dataTables_length select{vertical-align:middle;min-height:2.7142em}div.dataTables_wrapper div.dataTables_length .ui.selection.dropdown{min-width:0}div.dataTables_wrapper div.dataTables_filter input{margin-left:0.5em}div.dataTables_wrapper div.dataTables_info{padding-top:13px;white-space:nowrap}div.dataTables_wrapper div.dataTables_processing{position:absolute;top:50%;left:50%;width:200px;margin-left:-100px;text-align:center}div.dataTables_wrapper div.row.dt-table{padding:0}div.dataTables_wrapper div.dataTables_scrollHead table.dataTable{border-bottom-right-radius:0;border-bottom-left-radius:0;border-bottom:none}div.dataTables_wrapper div.dataTables_scrollBody thead .sorting:after,div.dataTables_wrapper div.dataTables_scrollBody thead .sorting_asc:after,div.dataTables_wrapper div.dataTables_scrollBody thead .sorting_desc:after{display:none}div.dataTables_wrapper div.dataTables_scrollBody table.dataTable{border-radius:0;border-top:none;border-bottom-width:0}div.dataTables_wrapper div.dataTables_scrollBody table.dataTable.no-footer{border-bottom-width:1px}div.dataTables_wrapper div.dataTables_scrollFoot table.dataTable{border-top-right-radius:0;border-top-left-radius:0;border-top:none}
2 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/css/datatables/dataTables.uikit.css:
--------------------------------------------------------------------------------
1 | table.dataTable {
2 | clear: both;
3 | margin-top: 6px !important;
4 | margin-bottom: 6px !important;
5 | max-width: none !important;
6 | }
7 | table.dataTable td,
8 | table.dataTable th {
9 | -webkit-box-sizing: content-box;
10 | box-sizing: content-box;
11 | }
12 | table.dataTable td.dataTables_empty,
13 | table.dataTable th.dataTables_empty {
14 | text-align: center;
15 | }
16 | table.dataTable.nowrap th,
17 | table.dataTable.nowrap td {
18 | white-space: nowrap;
19 | }
20 |
21 | div.dataTables_wrapper div.row.uk-grid.dt-merge-grid {
22 | margin-top: 5px;
23 | }
24 | div.dataTables_wrapper div.dataTables_length label {
25 | font-weight: normal;
26 | text-align: left;
27 | white-space: nowrap;
28 | }
29 | div.dataTables_wrapper div.dataTables_length select {
30 | width: 75px;
31 | display: inline-block;
32 | }
33 | div.dataTables_wrapper div.dataTables_filter {
34 | text-align: right;
35 | }
36 | div.dataTables_wrapper div.dataTables_filter label {
37 | font-weight: normal;
38 | white-space: nowrap;
39 | text-align: left;
40 | }
41 | div.dataTables_wrapper div.dataTables_filter input {
42 | margin-left: 0.5em;
43 | display: inline-block;
44 | width: auto;
45 | }
46 | div.dataTables_wrapper div.dataTables_info {
47 | padding-top: 8px;
48 | white-space: nowrap;
49 | }
50 | div.dataTables_wrapper div.dataTables_paginate {
51 | margin: 0;
52 | white-space: nowrap;
53 | text-align: right;
54 | }
55 | div.dataTables_wrapper div.dataTables_paginate ul.pagination {
56 | margin: 2px 0;
57 | white-space: nowrap;
58 | }
59 | div.dataTables_wrapper div.dataTables_processing {
60 | position: absolute;
61 | top: 50%;
62 | left: 50%;
63 | width: 200px;
64 | margin-left: -100px;
65 | margin-top: -26px;
66 | text-align: center;
67 | padding: 1em 0;
68 | }
69 |
70 | table.dataTable thead > tr > th,
71 | table.dataTable thead > tr > td {
72 | position: relative;
73 | }
74 | table.dataTable thead > tr > th.sorting_asc, table.dataTable thead > tr > th.sorting_desc, table.dataTable thead > tr > th.sorting,
75 | table.dataTable thead > tr > td.sorting_asc,
76 | table.dataTable thead > tr > td.sorting_desc,
77 | table.dataTable thead > tr > td.sorting {
78 | padding-right: 30px;
79 | }
80 | table.dataTable thead > tr > th.sorting:after, table.dataTable thead > tr > th.sorting_asc:after, table.dataTable thead > tr > th.sorting_desc:after,
81 | table.dataTable thead > tr > td.sorting:after,
82 | table.dataTable thead > tr > td.sorting_asc:after,
83 | table.dataTable thead > tr > td.sorting_desc:after {
84 | position: absolute;
85 | top: 7px;
86 | right: 8px;
87 | display: block;
88 | font-family: 'FontAwesome';
89 | }
90 | table.dataTable thead > tr > th.sorting:after,
91 | table.dataTable thead > tr > td.sorting:after {
92 | content: "\f0dc";
93 | color: #ddd;
94 | font-size: 0.8em;
95 | padding-top: 0.12em;
96 | }
97 | table.dataTable thead > tr > th.sorting_asc:after,
98 | table.dataTable thead > tr > td.sorting_asc:after {
99 | content: "\f0de";
100 | }
101 | table.dataTable thead > tr > th.sorting_desc:after,
102 | table.dataTable thead > tr > td.sorting_desc:after {
103 | content: "\f0dd";
104 | }
105 |
106 | div.dataTables_scrollHead table.dataTable {
107 | margin-bottom: 0 !important;
108 | }
109 |
110 | div.dataTables_scrollBody table {
111 | border-top: none;
112 | margin-top: 0 !important;
113 | margin-bottom: 0 !important;
114 | }
115 | div.dataTables_scrollBody table thead .sorting:after,
116 | div.dataTables_scrollBody table thead .sorting_asc:after,
117 | div.dataTables_scrollBody table thead .sorting_desc:after {
118 | display: none;
119 | }
120 | div.dataTables_scrollBody table tbody tr:first-child th,
121 | div.dataTables_scrollBody table tbody tr:first-child td {
122 | border-top: none;
123 | }
124 |
125 | div.dataTables_scrollFoot table {
126 | margin-top: 0 !important;
127 | border-top: none;
128 | }
129 |
130 | @media screen and (max-width: 767px) {
131 | div.dataTables_wrapper div.dataTables_length,
132 | div.dataTables_wrapper div.dataTables_filter,
133 | div.dataTables_wrapper div.dataTables_info,
134 | div.dataTables_wrapper div.dataTables_paginate {
135 | text-align: center;
136 | }
137 | }
138 | table.dataTable.uk-table-condensed > thead > tr > th {
139 | padding-right: 20px;
140 | }
141 | table.dataTable.uk-table-condensed .sorting:after,
142 | table.dataTable.uk-table-condensed .sorting_asc:after,
143 | table.dataTable.uk-table-condensed .sorting_desc:after {
144 | top: 6px;
145 | right: 6px;
146 | }
147 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/css/datatables/dataTables.uikit.min.css:
--------------------------------------------------------------------------------
1 | table.dataTable{clear:both;margin-top:6px !important;margin-bottom:6px !important;max-width:none !important}table.dataTable td,table.dataTable th{-webkit-box-sizing:content-box;box-sizing:content-box}table.dataTable td.dataTables_empty,table.dataTable th.dataTables_empty{text-align:center}table.dataTable.nowrap th,table.dataTable.nowrap td{white-space:nowrap}div.dataTables_wrapper div.row.uk-grid.dt-merge-grid{margin-top:5px}div.dataTables_wrapper div.dataTables_length label{font-weight:normal;text-align:left;white-space:nowrap}div.dataTables_wrapper div.dataTables_length select{width:75px;display:inline-block}div.dataTables_wrapper div.dataTables_filter{text-align:right}div.dataTables_wrapper div.dataTables_filter label{font-weight:normal;white-space:nowrap;text-align:left}div.dataTables_wrapper div.dataTables_filter input{margin-left:0.5em;display:inline-block;width:auto}div.dataTables_wrapper div.dataTables_info{padding-top:8px;white-space:nowrap}div.dataTables_wrapper div.dataTables_paginate{margin:0;white-space:nowrap;text-align:right}div.dataTables_wrapper div.dataTables_paginate ul.pagination{margin:2px 0;white-space:nowrap}div.dataTables_wrapper div.dataTables_processing{position:absolute;top:50%;left:50%;width:200px;margin-left:-100px;margin-top:-26px;text-align:center;padding:1em 0}table.dataTable thead>tr>th,table.dataTable thead>tr>td{position:relative}table.dataTable thead>tr>th.sorting_asc,table.dataTable thead>tr>th.sorting_desc,table.dataTable thead>tr>th.sorting,table.dataTable thead>tr>td.sorting_asc,table.dataTable thead>tr>td.sorting_desc,table.dataTable thead>tr>td.sorting{padding-right:30px}table.dataTable thead>tr>th.sorting:after,table.dataTable thead>tr>th.sorting_asc:after,table.dataTable thead>tr>th.sorting_desc:after,table.dataTable thead>tr>td.sorting:after,table.dataTable thead>tr>td.sorting_asc:after,table.dataTable thead>tr>td.sorting_desc:after{position:absolute;top:7px;right:8px;display:block;font-family:'FontAwesome'}table.dataTable thead>tr>th.sorting:after,table.dataTable thead>tr>td.sorting:after{content:"\f0dc";color:#ddd;font-size:0.8em;padding-top:0.12em}table.dataTable thead>tr>th.sorting_asc:after,table.dataTable thead>tr>td.sorting_asc:after{content:"\f0de"}table.dataTable thead>tr>th.sorting_desc:after,table.dataTable thead>tr>td.sorting_desc:after{content:"\f0dd"}div.dataTables_scrollHead table.dataTable{margin-bottom:0 !important}div.dataTables_scrollBody table{border-top:none;margin-top:0 !important;margin-bottom:0 !important}div.dataTables_scrollBody table thead .sorting:after,div.dataTables_scrollBody table thead .sorting_asc:after,div.dataTables_scrollBody table thead .sorting_desc:after{display:none}div.dataTables_scrollBody table tbody tr:first-child th,div.dataTables_scrollBody table tbody tr:first-child td{border-top:none}div.dataTables_scrollFoot table{margin-top:0 !important;border-top:none}@media screen and (max-width: 767px){div.dataTables_wrapper div.dataTables_length,div.dataTables_wrapper div.dataTables_filter,div.dataTables_wrapper div.dataTables_info,div.dataTables_wrapper div.dataTables_paginate{text-align:center}}table.dataTable.uk-table-condensed>thead>tr>th{padding-right:20px}table.dataTable.uk-table-condensed .sorting:after,table.dataTable.uk-table-condensed .sorting_asc:after,table.dataTable.uk-table-condensed .sorting_desc:after{top:6px;right:6px}
2 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/css/element/fonts/element-icons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuaFramework/cua-arbiter/61b2ea5d8b7c825b75d0f333d202e5703e0565a9/arbiter-web/arbiter/static/arbiter/css/element/fonts/element-icons.ttf
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/css/element/fonts/element-icons.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuaFramework/cua-arbiter/61b2ea5d8b7c825b75d0f333d202e5703e0565a9/arbiter-web/arbiter/static/arbiter/css/element/fonts/element-icons.woff
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/css/index.css:
--------------------------------------------------------------------------------
1 |
2 | body {
3 | background-color: #f2f2f2;
4 | }
5 |
6 | .mu-drawer {
7 | background-color: #f2f2f2;
8 | }
9 |
10 | #slide-nav {
11 | white-space: nowrap;
12 | }
13 |
14 | .log-dialog {
15 | max-width: 1000px;
16 | }
17 |
18 | .log-dialog h3 {
19 | padding: 4px 4px 3px;
20 | }
21 |
22 | .log-dialog p {
23 | margin: 2px;
24 | font-size: 12px;
25 | }
26 |
27 | #root-case {
28 | display: none;
29 | }
30 |
31 | #code-paper {
32 | top: 0;
33 | height: 600px;
34 | bottom: 0;
35 | }
36 |
37 | #case-paper {
38 | position: fixed;
39 | left: 0;
40 | top: 60px;
41 | right: 0;
42 | width: auto;
43 | bottom: 0;
44 | overflow-y: auto;
45 | size: 14px;
46 | z-index: -1;
47 | }
48 |
49 | .flex-between {
50 | display: flex;
51 | align-items: center;
52 | justify-content: space-between;
53 | width: 100%;
54 |
55 | }
56 |
57 | .grey-text {
58 | color: #9e9e9e;
59 | }
60 |
61 | .brown800-text {
62 | color: #4e342e;
63 | }
64 |
65 | .paper-casename {
66 | margin-left: 30px;
67 | }
68 |
69 | .paper-pyname {
70 | margin-left: 30px;
71 | cursor: pointer;
72 | }
73 |
74 | .red-icon {
75 | color: #ff5722;
76 | }
77 |
78 | .blue-icon {
79 | color: #6fa9ff;
80 | }
81 |
82 | .green-icon {
83 | color: #8bc34a;
84 | }
85 |
86 | .long-large-paper {
87 | margin-right: 100px;
88 | margin-left: 20px;
89 | }
90 |
91 | .long-little-paper {
92 | height: 45px;
93 | margin-bottom: 20px;
94 | margin-right: 130px;
95 | margin-left: 30px;
96 | position: relative;
97 | }
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/css/login.css:
--------------------------------------------------------------------------------
1 | body {
2 | text-align: center;
3 | background: rgba(0,0,0,0.05);
4 | vertical-align:middle;
5 | }
6 |
7 | .login {
8 | margin:auto;
9 | width: 400px;
10 | height: 320px;
11 | position:absolute;
12 | z-index:99;
13 | top: 25%;
14 | left: 40%;
15 | }
16 |
17 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/css/material-icons.css:
--------------------------------------------------------------------------------
1 | /* fallback */
2 | @font-face {
3 | font-family: 'Material Icons';
4 | font-style: normal;
5 | font-weight: 400;
6 | src: local('Material Icons'), local('MaterialIcons-Regular'), url("../fonts/material/o_1bgljqsqrvbv78v8lu1fsr1trca.woff2") format('woff2');
7 | }
8 |
9 | .material-icons {
10 | font-family: 'Material Icons';
11 | font-weight: normal;
12 | font-style: normal;
13 | font-size: 24px;
14 | line-height: 1;
15 | letter-spacing: normal;
16 | text-transform: none;
17 | display: inline-block;
18 | white-space: nowrap;
19 | word-wrap: normal;
20 | direction: ltr;
21 | -webkit-font-feature-settings: 'liga';
22 | -webkit-font-smoothing: antialiased;
23 | }
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/css/navbar.css:
--------------------------------------------------------------------------------
1 | .mu-appbar {
2 | height: 56px;
3 | }
4 |
5 | .mu-appbar-title {
6 | line-height: 56px;
7 | }
8 |
9 | .appbar-search-field {
10 | color: #FFF;
11 | margin-bottom: 0;
12 | }
13 |
14 | #arbiter-header {
15 | position: fixed;
16 | left: 0;
17 | right: 0;
18 | top: 0;
19 | width: auto;
20 | }
21 | #arbiter-navbar {
22 | position: fixed;
23 | left: 0;
24 | right: 0;
25 | top: 0;
26 | width: auto;
27 | }
28 |
29 | .slider-open {
30 | left: 256px !important;
31 | }
32 |
33 | #arbiter-navbar h2 {
34 | width: 300px;
35 | }
36 |
37 | #arbiter-header .mu-avatar {
38 | margin: 30px;
39 | cursor: pointer;
40 | }
41 |
42 | #arbiter-navbar .mu-avatar {
43 | margin: 30px;
44 | cursor: pointer;
45 | }
46 |
47 | #arbiter-navbar .mu-text-field {
48 |
49 | width: 80%;
50 |
51 | }
52 |
53 | .appbar-search-field.focus-state {
54 | color: #FFF;
55 | }
56 |
57 | .appbar-search-field .mu-text-field-hint {
58 | color: rgba(255, 255, 255, 0.54);
59 | }
60 |
61 | .appbar-search-field .mu-text-field-input {
62 | color: #FFF;
63 | }
64 |
65 | .appbar-search-field .mu-text-field-focus-line {
66 | background-color: #FFF;
67 | }
68 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/css/scrollbar/app.css:
--------------------------------------------------------------------------------
1 |
2 |
3 | .my-scrollbar {
4 | max-height: 100%;
5 | }
6 |
7 | .scroll-me {
8 | background: #EEE;
9 | /*min-width: 750px;*/
10 | }
11 |
12 | .kolom {
13 | display: inline-block;
14 | margin: 15px;
15 | }
16 |
17 | .clearfix {
18 | clear: both;
19 | }
20 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/css/scrollbar/vue2-scrollbar.css:
--------------------------------------------------------------------------------
1 | .vue-scrollbar-transition, .vue-scrollbar__scrollbar-vertical, .vue-scrollbar__scrollbar-horizontal {
2 | transition: all 0.5s ease;
3 | -moz-transition: all 0.5s ease;
4 | -webkit-transition: all 0.5s ease;
5 | -o-transition: all 0.5s ease;
6 | }
7 | .vue-scrollbar-transition--scrollbar {
8 | transition: opacity 0.5s linear;
9 | -moz-transition: opacity 0.5s linear;
10 | -webkit-transition: opacity 0.5s linear;
11 | -o-transition: opacity 0.5s linear;
12 | }
13 |
14 | .vue-scrollbar__wrapper {
15 | margin: 0 auto;
16 | overflow: hidden;
17 | position: relative;
18 | }
19 | .vue-scrollbar__wrapper:hover .vue-scrollbar__scrollbar-vertical, .vue-scrollbar__wrapper:hover .vue-scrollbar__scrollbar-horizontal {
20 | opacity: 1;
21 | }
22 | .vue-scrollbar__scrollbar-vertical, .vue-scrollbar__scrollbar-horizontal {
23 | opacity: 0.5;
24 | position: absolute;
25 | background: transparent;
26 | }
27 | .vue-scrollbar__scrollbar-vertical:hover, .vue-scrollbar__scrollbar-horizontal:hover {
28 | background: rgba(0, 0, 0, 0.3);
29 | }
30 | .vue-scrollbar__scrollbar-vertical .scrollbar, .vue-scrollbar__scrollbar-horizontal .scrollbar {
31 | position: relative;
32 | background: rgba(0, 0, 0, 0.5);
33 | cursor: default;
34 | }
35 | .vue-scrollbar__scrollbar-vertical {
36 | width: 10px;
37 | height: 100%;
38 | top: 0;
39 | right: 0;
40 | }
41 | .vue-scrollbar__scrollbar-vertical .scrollbar {
42 | width: 10px;
43 | }
44 | .vue-scrollbar__scrollbar-horizontal {
45 | height: 10px;
46 | width: 100%;
47 | bottom: 0;
48 | right: 0;
49 | }
50 | .vue-scrollbar__scrollbar-horizontal .scrollbar {
51 | height: 10px;
52 | }
53 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/css/wholog/index.css:
--------------------------------------------------------------------------------
1 | body {
2 |
3 | }
4 |
5 | #log-root {
6 | background: rgba(0, 0, 0, 0.05);
7 | vertical-align: middle;
8 | height: 100%;
9 | width: 100%;
10 | margin: 10px;
11 |
12 | }
13 |
14 | .query {
15 | display: flex;
16 | justify-content: center;
17 | margin-bottom: 20px;
18 | }
19 |
20 | .query-content span {
21 | font-weight: 500;
22 | font-size: large;
23 | }
24 |
25 | .query-button {
26 | display: flex;
27 | justify-content: center;
28 | }
29 |
30 | a {
31 | text-decoration: underline;
32 | color: #6495ED;
33 | }
34 | .red-icon {
35 | color: #ff5722;
36 | }
37 | .blue-icon {
38 | color: #6fa9ff;
39 | }
40 | a:hover {
41 | font-size: 120%;
42 | }
43 | .log-table-expand {
44 | font-size: 0;
45 | }
46 | .log-table-expand label {
47 | width: 90px;
48 | color: #99a9bf;
49 | }
50 | .log-table-expand .el-form-item {
51 | margin-right: 0;
52 | margin-bottom: 0;
53 | width: 30%;
54 | }
55 |
56 | #history-log {
57 | position: fixed;
58 | left: 0;
59 | top: 60px;
60 | right: 0;
61 | width: auto;
62 | bottom: 0;
63 | overflow-y: auto;
64 | size: 14px;
65 | z-index: -1;
66 | }
67 |
68 | .log-dialog {
69 | max-height: 360px;
70 | }
71 |
72 | .log-dialog p {
73 | margin: 5px;
74 | font-size: 12px;
75 | }
76 |
77 | .login-popup-top {
78 | width: 80%;
79 | opacity: .6;
80 | height: 48px;
81 | line-height: 48px;
82 | display: flex;
83 | align-items: center;
84 | justify-content: center;
85 | max-width: 375px;
86 | margin-top: 5px;
87 | color: red;
88 | background-color: #6495ED;
89 | }
90 |
91 | #arbiter-header {
92 | background-color: #6495ED;
93 | }
94 |
95 | .mu-appbar {
96 | background-color: #6495ED;
97 | }
98 |
99 | .login-dialog {
100 | padding-right: 20px;
101 | padding-bottom: 20px;
102 | height: 360px;
103 | width: 320px;
104 | }
105 |
106 | .login-dialog-btn {
107 | margin-right: 30px;
108 | margin-left: 25px;
109 | margin-top: 25px;
110 | width: 90%;
111 | }
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/css/wholog/statistic-log.css:
--------------------------------------------------------------------------------
1 | body {
2 |
3 | background: rgba(0, 0, 0, 0.05);
4 | vertical-align: middle;
5 | }
6 |
7 | #statistic-log {
8 | position: fixed;
9 | left: 0;
10 | top: 60px;
11 | right: 0;
12 | width: auto;
13 | bottom: 0;
14 | overflow-y: auto;
15 | size: 14px;
16 | z-index: -1;
17 | }
18 |
19 | #main {
20 | margin: 0 auto;
21 | width: 1000px;
22 | height: auto;
23 | }
24 |
25 | #result-content {
26 | margin: 0 auto;
27 | width: 1400px;
28 | height: 680px;
29 | }
30 |
31 | #main-chart {
32 | width: 1400px;
33 | height: 680px;
34 | }
35 |
36 | .login-dialog {
37 | padding-right: 20px;
38 | padding-bottom: 20px;
39 | height: 360px;
40 | width: 320px;
41 | }
42 |
43 | .login-dialog-btn {
44 | margin-right: 30px;
45 | margin-left: 25px;
46 | margin-top: 25px;
47 | width: 90%;
48 | }
49 |
50 | .log-dialog {
51 | max-height: 360px;
52 | }
53 |
54 | .log-dialog p {
55 | margin: 5px;
56 | font-size: 12px;
57 | }
58 | .log-chart-tooltip {
59 | word-wrap: break-word;
60 | word-break: break-all;
61 | }
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/fonts/material/o_1bgljqsqrvbv78v8lu1fsr1trca.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuaFramework/cua-arbiter/61b2ea5d8b7c825b75d0f333d202e5703e0565a9/arbiter-web/arbiter/static/arbiter/fonts/material/o_1bgljqsqrvbv78v8lu1fsr1trca.woff2
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/fonts/roboto/Roboto-Bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuaFramework/cua-arbiter/61b2ea5d8b7c825b75d0f333d202e5703e0565a9/arbiter-web/arbiter/static/arbiter/fonts/roboto/Roboto-Bold.woff
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/fonts/roboto/Roboto-Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuaFramework/cua-arbiter/61b2ea5d8b7c825b75d0f333d202e5703e0565a9/arbiter-web/arbiter/static/arbiter/fonts/roboto/Roboto-Bold.woff2
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/fonts/roboto/Roboto-Light.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuaFramework/cua-arbiter/61b2ea5d8b7c825b75d0f333d202e5703e0565a9/arbiter-web/arbiter/static/arbiter/fonts/roboto/Roboto-Light.woff
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/fonts/roboto/Roboto-Light.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuaFramework/cua-arbiter/61b2ea5d8b7c825b75d0f333d202e5703e0565a9/arbiter-web/arbiter/static/arbiter/fonts/roboto/Roboto-Light.woff2
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/fonts/roboto/Roboto-Medium.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuaFramework/cua-arbiter/61b2ea5d8b7c825b75d0f333d202e5703e0565a9/arbiter-web/arbiter/static/arbiter/fonts/roboto/Roboto-Medium.woff
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/fonts/roboto/Roboto-Medium.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuaFramework/cua-arbiter/61b2ea5d8b7c825b75d0f333d202e5703e0565a9/arbiter-web/arbiter/static/arbiter/fonts/roboto/Roboto-Medium.woff2
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/fonts/roboto/Roboto-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuaFramework/cua-arbiter/61b2ea5d8b7c825b75d0f333d202e5703e0565a9/arbiter-web/arbiter/static/arbiter/fonts/roboto/Roboto-Regular.woff
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/fonts/roboto/Roboto-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuaFramework/cua-arbiter/61b2ea5d8b7c825b75d0f333d202e5703e0565a9/arbiter-web/arbiter/static/arbiter/fonts/roboto/Roboto-Regular.woff2
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/fonts/roboto/Roboto-Thin.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuaFramework/cua-arbiter/61b2ea5d8b7c825b75d0f333d202e5703e0565a9/arbiter-web/arbiter/static/arbiter/fonts/roboto/Roboto-Thin.woff
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/fonts/roboto/Roboto-Thin.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuaFramework/cua-arbiter/61b2ea5d8b7c825b75d0f333d202e5703e0565a9/arbiter-web/arbiter/static/arbiter/fonts/roboto/Roboto-Thin.woff2
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/imgs/bg-pro.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuaFramework/cua-arbiter/61b2ea5d8b7c825b75d0f333d202e5703e0565a9/arbiter-web/arbiter/static/arbiter/imgs/bg-pro.png
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/imgs/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuaFramework/cua-arbiter/61b2ea5d8b7c825b75d0f333d202e5703e0565a9/arbiter-web/arbiter/static/arbiter/imgs/favicon.ico
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/imgs/progress.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuaFramework/cua-arbiter/61b2ea5d8b7c825b75d0f333d202e5703e0565a9/arbiter-web/arbiter/static/arbiter/imgs/progress.png
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/imgs/team_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuaFramework/cua-arbiter/61b2ea5d8b7c825b75d0f333d202e5703e0565a9/arbiter-web/arbiter/static/arbiter/imgs/team_logo.png
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/common/ace/mode-python.js:
--------------------------------------------------------------------------------
1 | define("ace/mode/python_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){var e="and|as|assert|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|not|or|pass|print|raise|return|try|while|with|yield",t="True|False|None|NotImplemented|Ellipsis|__debug__",n="abs|divmod|input|open|staticmethod|all|enumerate|int|ord|str|any|eval|isinstance|pow|sum|basestring|execfile|issubclass|print|super|binfile|iter|property|tuple|bool|filter|len|range|type|bytearray|float|list|raw_input|unichr|callable|format|locals|reduce|unicode|chr|frozenset|long|reload|vars|classmethod|getattr|map|repr|xrange|cmp|globals|max|reversed|zip|compile|hasattr|memoryview|round|__import__|complex|hash|min|set|apply|delattr|help|next|setattr|buffer|dict|hex|object|slice|coerce|dir|id|oct|sorted|intern",r=this.createKeywordMapper({"invalid.deprecated":"debugger","support.function":n,"constant.language":t,keyword:e},"identifier"),i="(?:r|u|ur|R|U|UR|Ur|uR)?",s="(?:(?:[1-9]\\d*)|(?:0))",o="(?:0[oO]?[0-7]+)",u="(?:0[xX][\\dA-Fa-f]+)",a="(?:0[bB][01]+)",f="(?:"+s+"|"+o+"|"+u+"|"+a+")",l="(?:[eE][+-]?\\d+)",c="(?:\\.\\d+)",h="(?:\\d+)",p="(?:(?:"+h+"?"+c+")|(?:"+h+"\\.))",d="(?:(?:"+p+"|"+h+")"+l+")",v="(?:"+d+"|"+p+")",m="\\\\(x[0-9A-Fa-f]{2}|[0-7]{3}|[\\\\abfnrtv'\"]|U[0-9A-Fa-f]{8}|u[0-9A-Fa-f]{4})";this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"string",regex:i+'"{3}',next:"qqstring3"},{token:"string",regex:i+'"(?=.)',next:"qqstring"},{token:"string",regex:i+"'{3}",next:"qstring3"},{token:"string",regex:i+"'(?=.)",next:"qstring"},{token:"constant.numeric",regex:"(?:"+v+"|\\d+)[jJ]\\b"},{token:"constant.numeric",regex:v},{token:"constant.numeric",regex:f+"[lL]\\b"},{token:"constant.numeric",regex:f+"\\b"},{token:r,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\+|\\-|\\*|\\*\\*|\\/|\\/\\/|%|<<|>>|&|\\||\\^|~|<|>|<=|=>|==|!=|<>|="},{token:"paren.lparen",regex:"[\\[\\(\\{]"},{token:"paren.rparen",regex:"[\\]\\)\\}]"},{token:"text",regex:"\\s+"}],qqstring3:[{token:"constant.language.escape",regex:m},{token:"string",regex:'"{3}',next:"start"},{defaultToken:"string"}],qstring3:[{token:"constant.language.escape",regex:m},{token:"string",regex:"'{3}",next:"start"},{defaultToken:"string"}],qqstring:[{token:"constant.language.escape",regex:m},{token:"string",regex:"\\\\$",next:"qqstring"},{token:"string",regex:'"|$',next:"start"},{defaultToken:"string"}],qstring:[{token:"constant.language.escape",regex:m},{token:"string",regex:"\\\\$",next:"qstring"},{token:"string",regex:"'|$",next:"start"},{defaultToken:"string"}]}};r.inherits(s,i),t.PythonHighlightRules=s}),define("ace/mode/folding/pythonic",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=t.FoldMode=function(e){this.foldingStartMarker=new RegExp("([\\[{])(?:\\s*)$|("+e+")(?:\\s*)(?:#.*)?$")};r.inherits(s,i),function(){this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i)return i[1]?this.openingBracketBlock(e,i[1],n,i.index):i[2]?this.indentationBlock(e,n,i.index+i[2].length):this.indentationBlock(e,n)}}.call(s.prototype)}),define("ace/mode/python",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/python_highlight_rules","ace/mode/folding/pythonic","ace/range"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text").Mode,s=e("./python_highlight_rules").PythonHighlightRules,o=e("./folding/pythonic").FoldMode,u=e("../range").Range,a=function(){this.HighlightRules=s,this.foldingRules=new o("\\:"),this.$behaviour=this.$defaultBehaviour};r.inherits(a,i),function(){this.lineCommentStart="#",this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.getTokenizer().getLineTokens(t,e),s=i.tokens;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"){var o=t.match(/^.*[\{\(\[:]\s*$/);o&&(r+=n)}return r};var e={pass:1,"return":1,raise:1,"break":1,"continue":1};this.checkOutdent=function(t,n,r){if(r!=="\r\n"&&r!=="\r"&&r!=="\n")return!1;var i=this.getTokenizer().getLineTokens(n.trim(),t).tokens;if(!i)return!1;do var s=i.pop();while(s&&(s.type=="comment"||s.type=="text"&&s.value.match(/^\s+$/)));return s?s.type=="keyword"&&e[s.value]:!1},this.autoOutdent=function(e,t,n){n+=1;var r=this.$getIndent(t.getLine(n)),i=t.getTabString();r.slice(-i.length)==i&&t.remove(new u(n,r.length-i.length,n,r.length))},this.$id="ace/mode/python"}.call(a.prototype),t.Mode=a})
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/common/ace/theme-chrome.js:
--------------------------------------------------------------------------------
1 | define("ace/theme/chrome",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!1,t.cssClass="ace-chrome",t.cssText='.ace-chrome .ace_gutter {background: #ebebeb;color: #333;overflow : hidden;}.ace-chrome .ace_print-margin {width: 1px;background: #e8e8e8;}.ace-chrome {background-color: #FFFFFF;color: black;}.ace-chrome .ace_cursor {color: black;}.ace-chrome .ace_invisible {color: rgb(191, 191, 191);}.ace-chrome .ace_constant.ace_buildin {color: rgb(88, 72, 246);}.ace-chrome .ace_constant.ace_language {color: rgb(88, 92, 246);}.ace-chrome .ace_constant.ace_library {color: rgb(6, 150, 14);}.ace-chrome .ace_invalid {background-color: rgb(153, 0, 0);color: white;}.ace-chrome .ace_fold {}.ace-chrome .ace_support.ace_function {color: rgb(60, 76, 114);}.ace-chrome .ace_support.ace_constant {color: rgb(6, 150, 14);}.ace-chrome .ace_support.ace_type,.ace-chrome .ace_support.ace_class.ace-chrome .ace_support.ace_other {color: rgb(109, 121, 222);}.ace-chrome .ace_variable.ace_parameter {font-style:italic;color:#FD971F;}.ace-chrome .ace_keyword.ace_operator {color: rgb(104, 118, 135);}.ace-chrome .ace_comment {color: #236e24;}.ace-chrome .ace_comment.ace_doc {color: #236e24;}.ace-chrome .ace_comment.ace_doc.ace_tag {color: #236e24;}.ace-chrome .ace_constant.ace_numeric {color: rgb(0, 0, 205);}.ace-chrome .ace_variable {color: rgb(49, 132, 149);}.ace-chrome .ace_xml-pe {color: rgb(104, 104, 91);}.ace-chrome .ace_entity.ace_name.ace_function {color: #0000A2;}.ace-chrome .ace_heading {color: rgb(12, 7, 255);}.ace-chrome .ace_list {color:rgb(185, 6, 144);}.ace-chrome .ace_marker-layer .ace_selection {background: rgb(181, 213, 255);}.ace-chrome .ace_marker-layer .ace_step {background: rgb(252, 255, 0);}.ace-chrome .ace_marker-layer .ace_stack {background: rgb(164, 229, 101);}.ace-chrome .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgb(192, 192, 192);}.ace-chrome .ace_marker-layer .ace_active-line {background: rgba(0, 0, 0, 0.07);}.ace-chrome .ace_gutter-active-line {background-color : #dcdcdc;}.ace-chrome .ace_marker-layer .ace_selected-word {background: rgb(250, 250, 255);border: 1px solid rgb(200, 200, 250);}.ace-chrome .ace_storage,.ace-chrome .ace_keyword,.ace-chrome .ace_meta.ace_tag {color: rgb(147, 15, 128);}.ace-chrome .ace_string.ace_regex {color: rgb(255, 0, 0)}.ace-chrome .ace_string {color: #1A1AA6;}.ace-chrome .ace_entity.ace_other.ace_attribute-name {color: #994409;}.ace-chrome .ace_indent-guide {background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y;}';var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)})
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/common/ace/theme-dawn.js:
--------------------------------------------------------------------------------
1 | define("ace/theme/dawn",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!1,t.cssClass="ace-dawn",t.cssText=".ace-dawn .ace_gutter {background: #ebebeb;color: #333}.ace-dawn .ace_print-margin {width: 1px;background: #e8e8e8}.ace-dawn {background-color: #F9F9F9;color: #080808}.ace-dawn .ace_cursor {color: #000000}.ace-dawn .ace_marker-layer .ace_selection {background: rgba(39, 95, 255, 0.30)}.ace-dawn.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #F9F9F9;}.ace-dawn .ace_marker-layer .ace_step {background: rgb(255, 255, 0)}.ace-dawn .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgba(75, 75, 126, 0.50)}.ace-dawn .ace_marker-layer .ace_active-line {background: rgba(36, 99, 180, 0.12)}.ace-dawn .ace_gutter-active-line {background-color : #dcdcdc}.ace-dawn .ace_marker-layer .ace_selected-word {border: 1px solid rgba(39, 95, 255, 0.30)}.ace-dawn .ace_invisible {color: rgba(75, 75, 126, 0.50)}.ace-dawn .ace_keyword,.ace-dawn .ace_meta {color: #794938}.ace-dawn .ace_constant,.ace-dawn .ace_constant.ace_character,.ace-dawn .ace_constant.ace_character.ace_escape,.ace-dawn .ace_constant.ace_other {color: #811F24}.ace-dawn .ace_invalid.ace_illegal {text-decoration: underline;font-style: italic;color: #F8F8F8;background-color: #B52A1D}.ace-dawn .ace_invalid.ace_deprecated {text-decoration: underline;font-style: italic;color: #B52A1D}.ace-dawn .ace_support {color: #691C97}.ace-dawn .ace_support.ace_constant {color: #B4371F}.ace-dawn .ace_fold {background-color: #794938;border-color: #080808}.ace-dawn .ace_list,.ace-dawn .ace_markup.ace_list,.ace-dawn .ace_support.ace_function {color: #693A17}.ace-dawn .ace_storage {font-style: italic;color: #A71D5D}.ace-dawn .ace_string {color: #0B6125}.ace-dawn .ace_string.ace_regexp {color: #CF5628}.ace-dawn .ace_comment {font-style: italic;color: #5A525F}.ace-dawn .ace_heading,.ace-dawn .ace_markup.ace_heading {color: #19356D}.ace-dawn .ace_variable {color: #234A97}.ace-dawn .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYLh/5+x/AAizA4hxNNsZAAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)})
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/common/ace/theme-github.js:
--------------------------------------------------------------------------------
1 | define("ace/theme/github",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!1,t.cssClass="ace-github",t.cssText='.ace-github .ace_gutter {background: #e8e8e8;color: #AAA;}.ace-github {background: #fff;color: #000;}.ace-github .ace_keyword {font-weight: bold;}.ace-github .ace_string {color: #D14;}.ace-github .ace_variable.ace_class {color: teal;}.ace-github .ace_constant.ace_numeric {color: #099;}.ace-github .ace_constant.ace_buildin {color: #0086B3;}.ace-github .ace_support.ace_function {color: #0086B3;}.ace-github .ace_comment {color: #998;font-style: italic;}.ace-github .ace_variable.ace_language {color: #0086B3;}.ace-github .ace_paren {font-weight: bold;}.ace-github .ace_boolean {font-weight: bold;}.ace-github .ace_string.ace_regexp {color: #009926;font-weight: normal;}.ace-github .ace_variable.ace_instance {color: teal;}.ace-github .ace_constant.ace_language {font-weight: bold;}.ace-github .ace_cursor {color: black;}.ace-github.ace_focus .ace_marker-layer .ace_active-line {background: rgb(255, 255, 204);}.ace-github .ace_marker-layer .ace_active-line {background: rgb(245, 245, 245);}.ace-github .ace_marker-layer .ace_selection {background: rgb(181, 213, 255);}.ace-github.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px white;}.ace-github.ace_nobold .ace_line > span {font-weight: normal !important;}.ace-github .ace_marker-layer .ace_step {background: rgb(252, 255, 0);}.ace-github .ace_marker-layer .ace_stack {background: rgb(164, 229, 101);}.ace-github .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgb(192, 192, 192);}.ace-github .ace_gutter-active-line {background-color : rgba(0, 0, 0, 0.07);}.ace-github .ace_marker-layer .ace_selected-word {background: rgb(250, 250, 255);border: 1px solid rgb(200, 200, 250);}.ace-github .ace_invisible {color: #BFBFBF}.ace-github .ace_print-margin {width: 1px;background: #e8e8e8;}.ace-github .ace_indent-guide {background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y;}';var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)})
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/common/ace/theme-iplastic.js:
--------------------------------------------------------------------------------
1 | define("ace/theme/iplastic",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!1,t.cssClass="ace-iplastic",t.cssText=".ace-iplastic .ace_gutter {background: #dddddd;color: #666666}.ace-iplastic .ace_print-margin {width: 1px;background: #bbbbbb}.ace-iplastic {background-color: #eeeeee;color: #333333}.ace-iplastic .ace_cursor {color: #333}.ace-iplastic .ace_marker-layer .ace_selection {background: #BAD6FD;}.ace-iplastic.ace_multiselect .ace_selection.ace_start {border-radius: 4px}.ace-iplastic .ace_marker-layer .ace_step {background: #444444}.ace-iplastic .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #49483E;background: #FFF799}.ace-iplastic .ace_marker-layer .ace_active-line {background: #e5e5e5}.ace-iplastic .ace_gutter-active-line {background-color: #eeeeee}.ace-iplastic .ace_marker-layer .ace_selected-word {border: 1px solid #555555;border-radius:4px}.ace-iplastic .ace_invisible {color: #999999}.ace-iplastic .ace_entity.ace_name.ace_tag,.ace-iplastic .ace_keyword,.ace-iplastic .ace_meta.ace_tag,.ace-iplastic .ace_storage {color: #0000FF}.ace-iplastic .ace_punctuation,.ace-iplastic .ace_punctuation.ace_tag {color: #000}.ace-iplastic .ace_constant {color: #333333;font-weight: 700}.ace-iplastic .ace_constant.ace_character,.ace-iplastic .ace_constant.ace_language,.ace-iplastic .ace_constant.ace_numeric,.ace-iplastic .ace_constant.ace_other {color: #0066FF;font-weight: 700}.ace-iplastic .ace_constant.ace_numeric{font-weight: 100}.ace-iplastic .ace_invalid {color: #F8F8F0;background-color: #F92672}.ace-iplastic .ace_invalid.ace_deprecated {color: #F8F8F0;background-color: #AE81FF}.ace-iplastic .ace_support.ace_constant,.ace-iplastic .ace_support.ace_function {color: #333333;font-weight: 700}.ace-iplastic .ace_fold {background-color: #464646;border-color: #F8F8F2}.ace-iplastic .ace_storage.ace_type,.ace-iplastic .ace_support.ace_class,.ace-iplastic .ace_support.ace_type {color: #3333fc;font-weight: 700}.ace-iplastic .ace_entity.ace_name.ace_function,.ace-iplastic .ace_entity.ace_other,.ace-iplastic .ace_entity.ace_other.ace_attribute-name,.ace-iplastic .ace_variable {color: #3366cc;font-style: italic}.ace-iplastic .ace_variable.ace_parameter {font-style: italic;color: #2469E0}.ace-iplastic .ace_string {color: #a55f03}.ace-iplastic .ace_comment {color: #777777;font-style: italic}.ace-iplastic .ace_fold-widget {background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42mWKsQ0AMAzC8ixLlrzQjzmBiEjp0A6WwBCSPgKAXoLkqSot7nN3yMwR7pZ32NzpKkVoDBUxKAAAAABJRU5ErkJggg==);}.ace-iplastic .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAABlJREFUeNpi+P//PwMzMzPzfwAAAAD//wMAGRsECSML/RIAAAAASUVORK5CYII=) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)})
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/common/common.js:
--------------------------------------------------------------------------------
1 | let run_socket = new WebSocket("ws://" + window.location.host + "/arbiter/");
2 | let edit_socket = new WebSocket("ws://" + window.location.host + "/arbiter/");
3 |
4 | function deleteAllCookies() {
5 | let cookies = document.cookie.split(";");
6 |
7 | for (let i = 0; i < cookies.length; i++) {
8 | let cookie = cookies[i];
9 | let eqPos = cookie.indexOf("=");
10 | let name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;
11 | document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 GMT";
12 | }
13 | }
14 |
15 | Date.prototype.format = function (fmt) {
16 | var o = {
17 | "M+": this.getMonth() + 1,
18 | "d+": this.getDate(),
19 | "H+": this.getHours(),
20 | "m+": this.getMinutes(),
21 | "s+": this.getSeconds(),
22 | "S+": this.getMilliseconds()
23 | };
24 |
25 | //因位date.getFullYear()出来的结果是number类型的,所以为了让结果变成字符串型,下面有两种方法:
26 |
27 |
28 | if (/(y+)/.test(fmt)) {
29 | //第一种:利用字符串连接符“+”给date.getFullYear()+"",加一个空字符串便可以将number类型转换成字符串。
30 |
31 | fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
32 | }
33 | for (var k in o) {
34 | if (new RegExp("(" + k + ")").test(fmt)) {
35 |
36 | //第二种:使用String()类型进行强制数据类型转换String(date.getFullYear()),这种更容易理解。
37 |
38 | fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(String(o[k]).length)));
39 | }
40 | }
41 | return fmt;
42 | };
43 |
44 |
45 | /**
46 | * 验证是否可编辑
47 | * @constructor
48 | */
49 | function ValidateEditWebSocket(fileName) {
50 | if ("WebSocket" in window) {
51 | edit_socket.onmessage = function (e) {
52 | console.log(e.data);
53 |
54 | };
55 | edit_socket.onopen = function () {
56 | //发送validateEdit 0 查询
57 | edit_socket.send("validateEdit 0 " + fileName);
58 | };
59 | // Call onopen directly if edit_socket is already open
60 | if (edit_socket.readyState === WebSocket.OPEN)
61 | edit_socket.onopen();
62 | }
63 | else {
64 | // 浏览器不支持 WebSocket
65 | alert("您的浏览器不支持 WebSocket!");
66 | }
67 | }
68 |
69 |
70 | function getusername() {
71 | let storage = window.localStorage;
72 | let username = storage['username'];
73 | return username ? username : null;
74 | }
75 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/common/get-res.js:
--------------------------------------------------------------------------------
1 | function getRes(requestPath,requestBody,jwtHeader) {
2 | return fetch(requestPath,
3 | {
4 | method: "POST",
5 | headers: {
6 | 'Accept': 'application/json, text/plain, */*',
7 | 'Content-Type': 'application/json',
8 | 'Authorization': (jwtHeader !== null) ? ("JWT "+jwtHeader) :""
9 | },
10 | body: JSON.stringify(requestBody)
11 | }).then((response) => {
12 | if(response.status === 401){
13 | console.log("权限验证失败,状态码为:" + response.status);
14 | window.location.href = "/arbiter/login";
15 | }
16 | else if (response.status !== 200) {
17 | console.log("存在一个问题,状态码为:" + response.status);
18 | const error = new Error(response.statusText);
19 | error.response = response;
20 | throw error;
21 | }
22 | else
23 | return response.json();
24 | })
25 | }
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/common/index.js:
--------------------------------------------------------------------------------
1 | //所有用到的组件
2 | let Event = new Vue();
3 |
4 | let getfilePath = function (key) {
5 | let casepath = key.substring(key.indexOf(".") + 1);
6 | casepath = casepath.substring(casepath.indexOf(".") + 1);
7 | let pyfilepath = casepath.split(":")[0].replace(/\./g, "/") + ".py";
8 | return pyfilepath;
9 | };
10 | let topaperMap = function (caseMap) {
11 | let paperMap = {};
12 | for (let [key, value] of Object.entries(caseMap)) {
13 | if (typeof value !== "object") {
14 | let pyfilepath = getfilePath(key);
15 | if (!!paperMap[pyfilepath] === false) {
16 | paperMap[pyfilepath] = {};
17 | }
18 | paperMap[pyfilepath][key] = value;
19 | }
20 | }
21 | return paperMap;
22 | };
23 | let toAllpaperMap = function (caseMap) {
24 | let paperMap = {};
25 | for (let [key, value] of Object.entries(caseMap)) {
26 | if (typeof value !== "object") {
27 | let pyfilepath = getfilePath(key);
28 | if (!!paperMap[pyfilepath] === false) {
29 | paperMap[pyfilepath] = {};
30 | }
31 | paperMap[pyfilepath][key] = value;
32 | }
33 | else {
34 | for (let [k, y] of Object.entries(value)) {
35 |
36 | let pyfilepath = getfilePath(key);
37 | if (!!paperMap[pyfilepath] === false) {
38 | paperMap[pyfilepath] = {};
39 | }
40 | paperMap[pyfilepath][k] = y;
41 | }
42 | }
43 |
44 | }
45 | return paperMap;
46 | };
47 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/common/snow.js:
--------------------------------------------------------------------------------
1 | const snow=function () {
2 | let canvas = document.querySelector('canvas');
3 | let ctx = canvas.getContext('2d');
4 | canvas.width = window.innerWidth;
5 | canvas.height = window.innerHeight;
6 | ctx.lineWidth = .3;
7 | ctx.strokeStyle = (new Color()).style;
8 |
9 | let dots = {
10 | nb: 40,
11 | distance: 50,
12 | d_radius: 100,
13 | array: []
14 | };
15 |
16 | function createColorStyle() {
17 | return 'rgba(0,0,0,0.1)';
18 | }
19 |
20 | function Color() {
21 |
22 | this.style = createColorStyle();
23 | }
24 |
25 | function Dot() {
26 | this.x = Math.random() * canvas.width;
27 | this.y = Math.random() * canvas.height;
28 |
29 | this.vx = -.5 + Math.random();
30 | this.vy = -.5 + Math.random();
31 |
32 | this.radius = Math.random() * 4;
33 |
34 | this.color = new Color();
35 | }
36 |
37 | Dot.prototype = {
38 | draw: function () {
39 | ctx.beginPath();
40 | ctx.fillStyle = this.color.style;
41 | ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
42 | ctx.fill();
43 | }
44 | };
45 |
46 | function createDots() {
47 | for (let i = 0; i < dots.nb; i++) {
48 | dots.array.push(new Dot());
49 | }
50 | }
51 |
52 | function moveDots() {
53 | for (let i = 0; i < dots.nb; i++) {
54 |
55 | let dot = dots.array[i];
56 |
57 | if (dot.y < 0 || dot.y > canvas.height) {
58 |
59 | dot.vy = -dot.vy;
60 | }
61 | else if (dot.x < 0 || dot.x > canvas.width) {
62 | dot.vx = -dot.vx;
63 | }
64 | dot.x += dot.vx;
65 | dot.y += dot.vy;
66 | }
67 | }
68 |
69 | function drawDots() {
70 | for (let i = 0; i < dots.nb; i++) {
71 | let dot = dots.array[i];
72 | dot.draw();
73 | }
74 | }
75 |
76 | function animateDots() {
77 | ctx.clearRect(0, 0, canvas.width, canvas.height);
78 | moveDots();
79 | // connectDots();
80 | drawDots();
81 |
82 | requestAnimationFrame(animateDots);
83 | }
84 |
85 |
86 | createDots();
87 | requestAnimationFrame(animateDots);
88 | };
89 | snow();
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/core/app.js:
--------------------------------------------------------------------------------
1 | let app = new Vue({
2 | router,
3 | el: '#app', store,
4 | data() {
5 | return {modelList: {}}
6 | },
7 | mounted() {
8 | this.flushAllCases().then(
9 | (json) => {
10 | Event.$emit('change-paper', json);
11 | document.getElementsByTagName("body")[0].style.display = "";
12 | this.modelList = json;
13 | }).catch((err) => {
14 | console.log("请求错误:" + err);
15 | });
16 | },
17 | methods: {
18 | ...Vuex.mapActions(['flushAllCases']),
19 |
20 | },
21 | components: { //要把组件写入到components里面,如果没有放的话在切换的时候就会找不到 组件
22 | 'ArbiterNavbar': ArbiterNavbar,
23 | 'ArbiterSlide': ArbiterSlide,
24 | 'CaseFloatBtn': CaseFloatBtn,
25 | 'CasePaper': CasePaper,
26 | }
27 | });
28 |
29 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/core/component/arbiter-navbar.js:
--------------------------------------------------------------------------------
1 | //顶部bar组件
2 | const ArbiterNavbar = {
3 | template: '#arbiterNavbar',
4 | store,
5 | computed: {
6 | usernameAbbreviation() {
7 | if (!!this.username()) {
8 | return this.username().substr(0, 2)
9 | }
10 | else
11 | return null;
12 | }
13 | },
14 | data: function () {
15 | return {
16 | message: {
17 | href: 'login',
18 | },
19 | sliderIsOpen: true,
20 | }
21 | },
22 | mounted() {
23 | this.refreshJwtToken();
24 | getRes("/arbiter/getUserDetail", null, this.jwtHeader()).then(
25 | json => {
26 | let storage = window.localStorage;
27 | storage["username"] = json["username"];
28 | storage["role"] = json["role"];
29 | // this.$store.commit('setUserName', json["username"]);
30 | this.setUserName(json["username"]);
31 |
32 | }
33 | ).catch((err) => {
34 | console.log("请求错误:" + err);
35 | });
36 | },
37 | methods: {
38 | ...Vuex.mapMutations(['setUserName', 'refreshJwtToken','setSlideOpen']),
39 | ...Vuex.mapGetters(['username', 'jwtHeader']),
40 | toggleSlide() {
41 | this.sliderIsOpen = !this.sliderIsOpen;
42 | this.setSlideOpen();
43 | }
44 | },
45 | components: { //要把组件写入到components里面,如果没有放的话在切换的时候就会找不到 组件
46 | 'userAvatar': userAvatar,
47 | 'menuIconButton': menuIconButton,
48 | }
49 |
50 | };
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/core/component/arbiter-slide.js:
--------------------------------------------------------------------------------
1 | //侧边菜单组件
2 | const ArbiterSlide = {
3 | props: {modelList: {}},
4 | template: '#arbiterNavSlide',
5 | store,
6 | data() {
7 | return {
8 | open: true,
9 | docked: true,
10 | value: "",
11 | dialog: false,
12 | gitInfo: {},
13 | gitCloneStatus: 'finish',
14 | }
15 | },
16 | computed: {
17 | slideOpen() {
18 | return this.getSlideOpen();
19 | },
20 | },
21 | watch: {
22 | slideOpen(val) {
23 | this.open = val;
24 | },
25 |
26 | },
27 | methods: {
28 | ...Vuex.mapGetters(['getSlideOpen', 'jwtHeader']),
29 | handleChange(val) {
30 | this.value = val;
31 | },
32 | openImportDialog() {
33 | this.dialog = true;
34 |
35 | },
36 | closeImportDialog() {
37 | this.dialog = false
38 | },
39 | cloneCaseObj() {
40 | this.gitCloneStatus = 'running';
41 |
42 | getRes("./cloneCaseObj", this.gitInfo, this.jwtHeader()).then(
43 | json => {
44 | window.location.href = window.location.href;
45 | }).catch((err) => {
46 | this.gitCloneStatus = 'finish';
47 | console.log("请求错误:" + err);
48 | });
49 | },
50 |
51 | toggle() {
52 | this.open = !this.open;
53 | },
54 | loadCasePaper(casemodel) {
55 | this.$router.push({name: 'casepath', params: {casemodel: casemodel}});
56 | },
57 |
58 | }
59 | };
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/core/component/case-float-btn.js:
--------------------------------------------------------------------------------
1 | //用例列表中的fab组件
2 | const CaseFloatBtn = {
3 | template: '#caseFloatBtn',
4 | data: function () {
5 | return {
6 | modalShow: true,
7 | seen: false,
8 | testCase: "",
9 | testName: "",
10 | logDialog: false,
11 | logContent: [],
12 | }
13 | }, mounted() {
14 | let _this = this;
15 | Event.$on('run-case', function (value) {
16 |
17 | _this.testCase = value.testCase;
18 | _this.testName = value.testName;
19 | _this.run();
20 | });
21 |
22 | },
23 | methods: {
24 | ...Vuex.mapGetters(['username', 'jwtHeader']),
25 | openLogDialog() {
26 | this.logDialog = true;
27 |
28 | },
29 | closeLogDialog() {
30 | this.logDialog = false
31 | },
32 | onMouseEnterCodeFAB() {
33 | this.seen = true;
34 | },
35 | onMouseleaveCodeFAB() {
36 | this.seen = false;
37 | },
38 | log() {
39 | this.logDialog = true;
40 | },
41 | cleanLog() {
42 | this.logContent = [];
43 | },
44 | run() {
45 |
46 | run_socket.onmessage = (res) => {
47 | this.logContent.push(res.data);
48 | // document.getElementById("insert").innerHTML += "";
49 |
50 | };
51 | run_socket.onopen = () => {
52 | run_socket.send("runCase " + this.testCase + " " + this.username()+ " " + this.testName);
53 | };
54 | // Call onopen directly if socket is already open
55 | if (run_socket.readyState === WebSocket.OPEN)
56 | run_socket.onopen();
57 |
58 | this.logDialog = true;
59 | }
60 | ,
61 | add() {
62 |
63 | },
64 | }
65 | };
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/core/component/case-paper.js:
--------------------------------------------------------------------------------
1 | //每个case的paper组件
2 | const CasePaper = {
3 | props: {casemodel: "", pyname: ""}, store,
4 | template: '#casePaper',
5 | components: {
6 | 'CodePaper': CodePaper,
7 | 'CodeFloatBtn': CodeFloatBtn,
8 | },
9 | data() {
10 | return {
11 | caseMap: {},
12 | cpath: null,
13 | copyDialog: false,
14 | deleteDialog: false,
15 | copyStatus: "finish",
16 | deleteStatus: "finish",
17 | fileInfo: {
18 | oldName: "",
19 | newName: "",
20 | },
21 | deleteFilePath: "",
22 | };
23 | },
24 | computed: {
25 | slideOpen() {
26 | return this.getSlideOpen();
27 | },
28 | },
29 | watch: {
30 | casemodel: function (val) {
31 | if (val.split(".").length < 3) {
32 | Event.$emit('change-paper', this.getAllCases());
33 | }
34 | else {
35 | Event.$emit('change-paper-all', this.getAllCases());
36 | }
37 | }
38 | },
39 | mounted() {
40 | let _this = this;
41 | Event.$on('change-paper', (caseMap) => {
42 | _this.caseMap = caseMap;
43 | _this.casemodel.split(".").forEach((element, index) => {
44 | _this.caseMap = _this.caseMap[element];
45 | });
46 | _this.caseMap = topaperMap(_this.caseMap);
47 | });
48 |
49 | Event.$on('change-paper-all', (caseMap) => {
50 | _this.caseMap = caseMap;
51 | _this.casemodel.split(".").forEach((element, index) => {
52 | _this.caseMap = _this.caseMap[element];
53 | });
54 | _this.caseMap = toAllpaperMap(_this.caseMap);
55 | });
56 |
57 | if (!!_this.getAllCases()) {
58 | Event.$emit('change-paper', _this.getAllCases());
59 | }
60 |
61 | }
62 | ,
63 | methods: {
64 | ...Vuex.mapGetters(['getAllCases', 'jwtHeader','getSlideOpen']),
65 | run(testCase,testName) {
66 | Event.$emit('run-case', {testCase:testCase,testName:testName,});
67 | },
68 | openDeleteDialog(value) {
69 | this.deleteDialog = true;
70 | this.deleteStatus = 'finish';
71 | let caseNamePath = null;
72 | for (let [k, v] of Object.entries(value)) {
73 | caseNamePath = k;
74 | }
75 | caseNamePath = caseNamePath.split(":")[0];
76 | let deletePath = caseNamePath.split(".").join("/") + ".py";
77 | this.deleteFilePath = deletePath.substring(deletePath.indexOf('/') + 1);
78 |
79 | },
80 | closeDeleteDialog() {
81 | this.deleteDialog = false
82 | },
83 | openCopyDialog(value) {
84 | this.copyDialog = true;
85 | this.copyStatus = 'finish';
86 | let caseNamePath = null;
87 | for (let [k, v] of Object.entries(value)) {
88 | caseNamePath = k;
89 | }
90 | caseNamePath = caseNamePath.split(":")[0];
91 | let oldpath = caseNamePath.split(".").join("/") + ".py";
92 | let newpath = caseNamePath.split(".").join("/") + "_copy.py";
93 | this.fileInfo.oldName = oldpath.substring(oldpath.indexOf('/') + 1);
94 | this.fileInfo.newName = newpath.substring(newpath.indexOf('/') + 1);
95 | },
96 | closeCopyDialog() {
97 | this.copyDialog = false
98 | },
99 | showcode(key, value) {
100 | if (this.$router.currentRoute.name !== 'casepathpy') {
101 | this.$router.push({name: 'casepathpy', params: {pyname: key}});
102 | }
103 | else {
104 | this.$router.push({name: 'casepath', params: {casemodel: this.casemodel}});
105 | }
106 |
107 | let caseNamePath = null;
108 | for (let [k, v] of Object.entries(value)) {
109 | caseNamePath = k;
110 | }
111 | caseNamePath = caseNamePath.split(":")[0];
112 | this.cpath = caseNamePath.split(".").join("/") + ".py";
113 | },
114 | copyFile() {
115 | this.copyStatus = 'running';
116 | getRes("/arbiter/copy", {
117 | oldPath: this.fileInfo.oldName,
118 | newPath: this.fileInfo.newName
119 | }, this.jwtHeader()).then(
120 | json => {
121 | window.location.href = window.location.href;
122 | }).catch((err) => {
123 | this.copyStatus = 'fail';
124 | console.log("请求错误:" + err);
125 | });
126 | },
127 | deleteFile() {
128 | this.deleteStatus = 'running';
129 | getRes("/arbiter/delete", {deleteFilePath: this.deleteFilePath}, this.jwtHeader()).then(
130 | json => {
131 | window.location.href = window.location.href;
132 | }).catch((err) => {
133 | this.deleteStatus = 'fail';
134 | console.log("请求错误:" + err);
135 | });
136 | },
137 |
138 | }
139 | };
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/core/component/code-float-btn.js:
--------------------------------------------------------------------------------
1 | //py文件paper中的fab组件
2 | const CodeFloatBtn = {
3 | template: '#codeFloatBtn', store,
4 | props: {
5 | pypath: null,
6 | casemodel: null
7 |
8 | },
9 | data: function () {
10 | return {
11 | modalShow: true,
12 | seen: false,
13 | editIcon: "mode_edit",
14 | saveDialog: false,
15 | logDialog: false,
16 | saveStatus: 'finish',
17 | logContent: [],
18 | path: null
19 | }
20 | }, mounted() {
21 | this.path = this.pypath;
22 |
23 | },
24 | methods: {
25 | ...Vuex.mapMutations(['setUserName', 'refreshJwtToken',]),
26 | ...Vuex.mapGetters(['username', 'jwtHeader']),
27 | openSaveDialog() {
28 | this.saveDialog = true;
29 |
30 | },
31 | openLogDialog() {
32 | this.logDialog = true;
33 |
34 | },
35 | closeLogDialog() {
36 | this.logDialog = false
37 | },
38 | onMouseEnterCodeFAB() {
39 | this.seen = true;
40 | },
41 | onMouseleaveCodeFAB() {
42 | this.seen = false;
43 | },
44 | log() {
45 | this.logDialog = true;
46 | },
47 | cleanLog() {
48 | this.logContent = [];
49 | },
50 | edit() {
51 | let codeContent = ace.edit("code-paper");
52 | if (this.editIcon === "mode_edit") {
53 |
54 | codeContent.setReadOnly(false);//设置为可编辑模式
55 | codeContent.setTheme("ace/theme/chrome");//设置可编辑状态主题
56 | this.editIcon = "save";
57 | }
58 | else if (this.editIcon === "save") {
59 | let caseNamePath = null;
60 | for (let [k, v] of Object.entries(this.path)) {
61 | if (k) {
62 | caseNamePath = k;
63 | break;
64 | }
65 | }
66 | this.saveStatus = "running";
67 | this.saveDialog = true;
68 | let newCodeContent = codeContent.getValue();
69 | //检查响应文本
70 | getRes("/arbiter/save/", {
71 | casepath: caseNamePath,
72 | content: newCodeContent
73 | }, this.jwtHeader()).then((data) => {
74 | if (data['result'] === "ok") {
75 | this.editIcon = "mode_edit";
76 | let codeContent = ace.edit("code-paper");
77 | codeContent.setReadOnly(true);//设置为不可编辑模式
78 | this.saveDialog = false;
79 | this.$router.push({name: 'casepath', params: {casemodel: this.casemodel}});
80 | } else {
81 | alert("文件保存失败!");
82 | }
83 | }).catch((err) => {
84 | console.log("请求错误:" + err);
85 | })
86 | }
87 | }
88 | }
89 | };
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/core/component/code-paper.js:
--------------------------------------------------------------------------------
1 | //py文件的paper组件
2 | const CodePaper = {
3 | props: {pypathx: null,},
4 | data: function () {
5 | return {path: null}
6 | },
7 | template: '#codePaper',
8 | mounted() {
9 |
10 | this.path = this.pypathx;
11 | if (!!this.path) {
12 | for (let [k, v] of Object.entries(this.path)) {
13 | if (k) {
14 | caseNamePath = k;
15 | break;
16 | }
17 | }
18 | caseNamePath = caseNamePath.split(":")[0];
19 | this.path = caseNamePath.split(".").join("/") + ".py";
20 |
21 | this.loadCaseFile(this.path)
22 | }
23 |
24 | },
25 | methods: {
26 | showcode(key, value) {
27 | this.$router.push({name: 'casepathpy', params: {pyname: key}});
28 | let caseNamePath = null;
29 |
30 | for (let [k, v] of Object.entries(value)) {
31 | caseNamePath = k;
32 | }
33 | caseNamePath = caseNamePath.split(":")[0];
34 | this.path = caseNamePath.split(".").join("/") + ".py";
35 |
36 | },
37 | loadCaseFile(caseNamePath) {
38 |
39 | // document.getElementById("codecontent").style.fontSize = "14px";
40 | // document.getElementById("codecontent").style.height = "600px";
41 | let codeContent = ace.edit(this.$el);
42 | codeContent.setTheme("ace/theme/github");
43 | codeContent.setReadOnly(true);//设置只读
44 | codeContent.$blockScrolling = Infinity;
45 | codeContent.session.setMode("ace/mode/python");
46 | // setBtn("edit");
47 | /*查询可编辑状态*/
48 | new ValidateEditWebSocket(caseNamePath);
49 | let xhr = new XMLHttpRequest();
50 | xhr.open('GET', '/static/' + caseNamePath, true);
51 | xhr.setRequestHeader("If-Modified-Since", "0");
52 | xhr.onreadystatechange = function () {
53 | if (xhr.readyState === 4) {
54 | codeContent.setValue(xhr.responseText, -1);//设置显示内容,并将光标移动到start处
55 | }
56 | };
57 | xhr.send(null);
58 | }
59 |
60 | }
61 | };
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/core/component/menu-icon-Button.js:
--------------------------------------------------------------------------------
1 | //菜单图标和其下拉菜单组件
2 | const menuIconButton = {
3 | template: '#menuIconButton', store,
4 | props: {usernameAbbreviation: null},
5 | data: function () {
6 | return {
7 | appMenuTrigger: null,
8 | appMenuOpen: false,
9 | }
10 | },
11 | mounted() {
12 | this.appMenuTrigger = this.$refs.appIcon.$el;
13 | },
14 | methods: {
15 | ...Vuex.mapMutations(['setUserName', 'refreshJwtToken',]),
16 | ...Vuex.mapGetters(['username', 'jwtHeader']),
17 | appMenuToggle() {
18 | this.appMenuOpen = !this.appMenuOpen
19 | },
20 | appMenuHandleClose(e) {
21 | this.appMenuOpen = false
22 | },
23 | }
24 | };
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/core/component/user-avatar.js:
--------------------------------------------------------------------------------
1 | //用户图标和其下拉菜单组件
2 | const userAvatar = {
3 | template: '#userAvatar',
4 | store,
5 | props: {usernameAbbreviation: null},
6 | data: function () {
7 | return {
8 | userMenuTrigger: null,
9 | userMenuOpen: false,
10 | }
11 | },
12 | mounted() {
13 | this.userMenuTrigger = this.$refs.UserAvatar.$el;
14 | },
15 | methods: {
16 | ...Vuex.mapMutations(['setUserName', 'refreshJwtToken',]),
17 | userMenuToggle() {
18 | this.userMenuOpen = !this.userMenuOpen
19 | },
20 | userMenuHandleClose(e) {
21 | this.userMenuOpen = false
22 | }, logout() {
23 | deleteAllCookies();
24 | let storage = window.localStorage;
25 | storage.clear();
26 | this.setUserName(null);
27 | this.refreshJwtToken();
28 | },
29 | }
30 | };
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/core/route.js:
--------------------------------------------------------------------------------
1 | const router = new VueRouter({
2 | mode: 'history',
3 | base: "arbiter",
4 | routes: [
5 | {path: '/'},
6 | {
7 | path: '/:casemodel',
8 | name: 'casepath',
9 | components: {paper: CasePaper,},
10 | props: {paper: true,}
11 | },
12 | {
13 | path: '/:casemodel/:pyname',
14 | name: 'casepathpy',
15 | components: {paper: CasePaper, codefab: CodeFloatBtn},
16 | props: {paper: true, codefab: true}
17 | },
18 |
19 | ]
20 | });
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/login.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Administrator on 2017/8/6.
3 | */
4 |
5 | const login_app = new Vue({
6 | el: '#login-form',
7 | data: {
8 | inputtext: {},
9 | prompt: "",
10 | },
11 | methods: {
12 | submit(e) {
13 | fetch("api-token-auth",
14 | {
15 | method: "POST",
16 | credentials: "same-origin",
17 | headers: {
18 | 'Accept': 'application/json, text/plain, */*',
19 | 'Content-Type': 'application/json'
20 | },
21 | body: JSON.stringify(this.inputtext)
22 | }).then((response) => {
23 | if (response.status !== 200
24 | ) {
25 | this.prompt = "账号或密码错误";
26 | const error = new Error(response.statusText);
27 | error.response = response;
28 | throw error;
29 | }
30 | else
31 | return response.json();
32 | }).then(
33 | (msg) => {
34 | if (msg.token) {
35 | let storage = window.localStorage;
36 | storage["token"] = msg.token;
37 | window.location.href ="."
38 | }
39 | else {
40 | this.prompt = "获取登陆密钥失败";
41 | }
42 | }
43 | ).catch((err) => {
44 | console.log("登陆失败,服务端返回状态为:" + err);
45 | }
46 | );
47 | }
48 | }
49 | });
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/store.js:
--------------------------------------------------------------------------------
1 | //vuex:管理各个公用变量的store
2 |
3 | //vuex用户模块:管理登陆的用户数据
4 | const userModule = {
5 | state: {
6 | username: null,
7 | jwtToken: null,
8 | avatarPicPath: null,
9 | nickName: null,
10 | role: null,
11 | email: null,
12 | searchHistory: null,
13 | settings: {}
14 | },
15 | mutations: {
16 | setUserName(state, username) {
17 | state.username = username;
18 | },
19 | refreshJwtToken(state) {
20 | state.jwtToken = window.localStorage["token"];
21 | }
22 | },
23 | actions: {
24 | setAvatarPicPath(state, avatarPicPath) {
25 | state.avatarPicPath = avatarPicPath;
26 | }
27 | },
28 | getters: {
29 | username: state => {
30 | return state.username
31 | },
32 | jwtHeader: state => {
33 | return state.jwtToken
34 | }
35 | }
36 | };
37 | //vuex用例模块:管理当前项目的所有用例
38 | const caseModule = {
39 | state: {
40 | allCases: null,
41 | packageList: null,
42 | caseList: null,
43 | checkedCases: [],
44 | currentPyPath: null
45 | },
46 | mutations: {
47 | setAllCases(state, allCases) {
48 | state.allCases = allCases;
49 | },
50 | },
51 | actions: {
52 | flushAllCases({state, commit, rootState, rootGetters}) {
53 | return getRes("/arbiter/getCaseList", null, rootGetters.jwtHeader).then((json) => {
54 | commit("setAllCases", json);
55 | return json;
56 | });
57 | }
58 | },
59 | getters: {
60 | getAllCases: state => {
61 | return state.allCases
62 | }
63 | }
64 | // actions: { ... }
65 | };
66 |
67 | //vuex页面状态模块
68 | const pageModule = {
69 | state: {slideOpen: true},
70 | mutations: {
71 | setSlideOpen(state) {
72 | state.slideOpen = !state.slideOpen;
73 | },
74 | },
75 | getters: {
76 | getSlideOpen: state => {
77 | return state.slideOpen
78 | }
79 | }
80 | // actions: { ... }
81 | };
82 |
83 | //store:所有vuex模块的集合
84 | const store = new Vuex.Store({
85 | modules: {
86 | user: userModule,
87 | case: caseModule,
88 | page: pageModule
89 | }
90 | });
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/wholog/app.js:
--------------------------------------------------------------------------------
1 | let app = new Vue({
2 | router,
3 | el: '#app', store,
4 | data: {},
5 |
6 | /*组件集合*/
7 | components: {
8 | 'ArbiterHeader': ArbiterHeader,
9 | 'historyLog': historyLog,
10 | 'statisticLog':statisticLog,
11 | 'logSlide': logSlide,
12 | 'CaseFloatBtn': CaseFloatBtn,
13 |
14 | },
15 | });
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/wholog/component/header-components.js:
--------------------------------------------------------------------------------
1 | //所有用到的组件
2 | let Event = new Vue();
3 | //****以下为所有用到的组件:
4 | //用户图标和其下拉菜单组件
5 | const userAvatar = {
6 | template: '#userAvatar',
7 | store,
8 | props: {usernameAbbreviation: null},
9 | data: function () {
10 | return {
11 | userMenuTrigger: null,
12 | userMenuOpen: false,
13 | }
14 | },
15 | mounted() {
16 | this.userMenuTrigger = this.$refs.UserAvatar.$el;
17 | },
18 | methods: {
19 | ...Vuex.mapMutations(['setUserName', 'refreshJwtToken',]),
20 | userMenuToggle() {
21 | this.userMenuOpen = !this.userMenuOpen
22 | },
23 | userMenuHandleClose(e) {
24 | this.userMenuOpen = false
25 | }, logout() {
26 | deleteAllCookies();
27 | let storage = window.localStorage;
28 | storage.clear();
29 | this.setUserName(null);
30 | this.refreshJwtToken();
31 | },
32 | }
33 | };
34 | //菜单图标和其下拉菜单组件
35 | const menuIconButton = {
36 | template: '#menuIconButton', store,
37 | props: {usernameAbbreviation: null},
38 | data: function () {
39 | return {
40 | appMenuTrigger: null,
41 | appMenuOpen: false,
42 | dialog: false,
43 | gitUrlPrefix: '',
44 | gitCloneStatus: 'finish',
45 | }
46 | },
47 | mounted() {
48 | this.appMenuTrigger = this.$refs.appIcon.$el;
49 | },
50 | methods: {
51 | ...Vuex.mapMutations(['setUserName', 'refreshJwtToken',]),
52 | ...Vuex.mapGetters(['username', 'jwtHeader']),
53 | appMenuToggle() {
54 | this.appMenuOpen = !this.appMenuOpen
55 | },
56 | appMenuHandleClose(e) {
57 | this.appMenuOpen = false
58 | },
59 | closeImportDialog() {
60 | this.dialog = false
61 | },
62 | cloneCaseObj() {
63 | this.gitCloneStatus = 'running';
64 |
65 | getRes("./cloneCaseObj", {url: this.gitUrlPrefix}, this.jwtHeader()).then(
66 | json => {
67 | this.gitCloneStatus = 'finish';
68 | window.location.href = window.location.href;
69 | }).catch((err) => {
70 | this.gitCloneStatus = 'fail';
71 | console.log("请求错误:" + err);
72 | });
73 | },
74 | }
75 | };
76 | //顶部组件
77 | const ArbiterHeader = {
78 | template: '#arbiterHeader',
79 | store,
80 | computed: {
81 | usernameAbbreviation() {
82 | if (!!this.username()) {
83 | return this.username().substr(0, 2)
84 | }
85 | else
86 | return null;
87 | }
88 | },
89 | data: function () {
90 | return {
91 | message: {
92 | href: 'login',
93 | },
94 | sliderIsOpen: true,
95 | loginDialog: {
96 | switch: false,
97 | username: "",
98 | password: "",
99 |
100 | },
101 | }
102 | },
103 | mounted() {
104 | this.refreshJwtToken();
105 |
106 | getRes("./getUserDetail", null, this.jwtHeader()).then(
107 | json => {
108 | let storage = window.localStorage;
109 | storage["username"] = json["username"];
110 | storage["role"] = json["role"];
111 | // this.$store.commit('setUserName', json["username"]);
112 | this.setUserName(json["username"]);
113 | }
114 | ).catch((err) => {
115 | console.log("请求错误:" + err);
116 | });
117 | },
118 | methods: {
119 | ...Vuex.mapMutations(['setUserName', 'refreshJwtToken','setSlideOpen']),
120 | ...Vuex.mapGetters(['username', 'jwtHeader']),
121 | toggleSlide() {
122 | this.sliderIsOpen = !this.sliderIsOpen;
123 | this.setSlideOpen();
124 | },
125 | /*点击登录*/
126 | toLogin() {
127 | this.openLoginDialog();
128 | },
129 | submit() {
130 |
131 | },
132 | /*打开和关闭登录对话框*/
133 | openLoginDialog() {
134 | this.loginDialog.switch = true;
135 | },
136 | closeLoginDialog() {
137 | this.loginDialog.switch = false;
138 | },
139 | },
140 | components: { //要把组件写入到components里面,如果没有放的话在切换的时候就会找不到 组件
141 | 'userAvatar': userAvatar,
142 | 'menuIconButton': menuIconButton,
143 | }
144 |
145 | };
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/wholog/component/history-log.js:
--------------------------------------------------------------------------------
1 | /*所有组件*/
2 | /**/
3 | const historyLog = {
4 | template: '#historyLog',
5 | store,
6 | data: function () {
7 | let now = new Date();
8 | now.setDate(now.getDate() + 1);
9 | return {
10 | loginPopup: false, /*未登录是提示popup*/
11 | startDate: new Date().format("yyyy-MM-dd"),
12 | startTime: '00:00',
13 | endDate: now.format("yyyy-MM-dd"),
14 | endTime: '00:00',
15 | tableData: [],
16 | tableTotal: 0,
17 | logDialog: {
18 | menus: [],
19 | content: [],
20 | switch: false,
21 | }
22 | }
23 | },
24 | computed: {
25 | slideOpen() {
26 | return this.getSlideOpen();
27 | },
28 | },
29 | mounted() {
30 | this.refreshJwtToken();
31 | this.queryData();
32 | },
33 | /*方法*/
34 | methods: {
35 | /*存到vuex map 方便调用store里函数*/
36 | ...Vuex.mapMutations(['setUserName', 'refreshJwtToken',]),
37 | ...Vuex.mapGetters(['username', 'jwtHeader', 'getSlideOpen']),
38 | /*查询运行列表*/
39 | queryData() {
40 | let startTime = this.startDate + " " + this.startTime;
41 | let endTime = this.endDate + " " + this.endTime;
42 | fetch('../wholog/getAllLog',
43 | {
44 | method: 'POST',
45 | credentials: "same-origin",
46 | headers: {
47 | 'Accept': 'application/json, text/plain, */*',
48 | 'Content-Type': 'application/json',
49 | 'Authorization': "JWT " + this.jwtHeader(),
50 | },
51 | body: JSON.stringify({startTime: startTime, endTime: endTime})
52 | }).then((response) => {
53 | /*判断请求状态码*/
54 | if (response.status !== 200) {
55 | if (response.status === 401) {
56 | this.openLoginPopup();
57 | /*判断未登录时 去打开登录提示*/
58 | } else {
59 | console.log("请求失败,状态码为:" + response.status);
60 |
61 | }
62 | } else {
63 | return response.json();
64 | }
65 | }).then((json) => {
66 | /*给tableData赋值*/
67 | this.tableData = json['data'];
68 | this.tableTotal = json['total'];
69 | }).catch((err) => {
70 | console.log("请求wholog/getAllLog出错:" + err);
71 | });
72 |
73 | },
74 | /*删除一条记录*/
75 | deleteLog(logId) {
76 | getRes("/arbiter/wholog/deleteLog", {
77 | log_id: logId,
78 | }, this.jwtHeader()).then((json) => {
79 | this.queryData()
80 | })
81 |
82 | },
83 | /*查询对应记录下的详细运行日志记录*/
84 | queryDetailData(logId) {
85 | /*对logId进行处理兼容es*/
86 | logId = logId.replace(/-/g, "");
87 | fetch('../wholog/queryLogData',
88 | {
89 | method: 'POST',
90 | credentials: "same-origin",
91 | headers: {
92 | 'Accept': 'application/json, text/plain, */*',
93 | 'Content-Type': 'application/json',
94 | 'Authorization': "JWT " + this.jwtHeader()
95 | },
96 | body: JSON.stringify({logId: logId})
97 | }).then((response) => {
98 | /*判断请求状态码*/
99 | if (response.status !== 200) {
100 | if (response.status === 401) {
101 | this.openLoginPopup();
102 | /*判断未登录时 去打开登录提示*/
103 | } else {
104 | console.log("请求失败,状态码为:" + response.status);
105 | }
106 | } else {
107 | return response.json();
108 | }
109 | }).then((json) => {
110 | console.log("请求成功,打开dialog");
111 | this.logDialog.menus = json['data'];
112 | this.openDialog();
113 | }).catch((err) => {
114 | console.log("请求wholog/queryLogData出错:" + err);
115 | });
116 |
117 | }, /*queryDetailData end*/
118 | filterTag(value, row) {
119 | return row.result === value;
120 | },
121 | /*打开和关闭日志运行详情对话框*/
122 | openDialog() {
123 | this.logDialog.switch = true;
124 | },
125 | closeDialog() {
126 | this.logDialog.switch = false;
127 | },
128 | /*打开登录提示框*/
129 | openLoginPopup() {
130 | this.loginPopup = true;
131 | },
132 | run(testCase,testName) {
133 | Event.$emit('run-case', {testCase:testCase,testName:testName,});
134 | },
135 | }, /*method end*/
136 |
137 | watch: {
138 | loginPopup(val) {
139 | if (val) {
140 | setTimeout(() => {
141 | this.loginPopup = false;
142 | }, 1500);
143 | }
144 | }
145 | }, /*watch end*/
146 |
147 | };
148 |
149 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/wholog/component/log-slide.js:
--------------------------------------------------------------------------------
1 | //侧边菜单组件
2 | const logSlide = {
3 | template: '#logSlide',
4 | store,
5 | data() {
6 | return {
7 | open: true,
8 | docked: true,
9 | value: ""
10 | }
11 | },
12 | computed: {
13 | slideOpen() {
14 | return this.getSlideOpen();
15 | },
16 | },
17 | watch: {
18 | slideOpen(val) {
19 | this.open = val;
20 | },
21 |
22 | },
23 |
24 | methods: {
25 | ...Vuex.mapGetters(['getSlideOpen']),
26 | handleChange(val) {
27 | this.typeList = val;
28 | },
29 |
30 | toggle() {
31 | this.open = !this.open;
32 | },
33 | //路由跳转-index
34 | routerToIndex() {
35 | this.$router.push({name: 'index'});
36 | },
37 | //路由跳转-历史日志
38 | routerToHistoryLog() {
39 | //this.$router.push({name: 'casepath', params: {casemodel: casemodel}});
40 | this.$router.push({name: 'historyLog'});
41 | },
42 | //路由跳转-图表日志
43 | routerToStatisticLog() {
44 | this.$router.push({name: 'statisticLog'});
45 | }
46 |
47 |
48 | }
49 | };
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/wholog/component/statistic-log.js:
--------------------------------------------------------------------------------
1 | /*所有组件*/
2 | /**/
3 | const statisticLog = {
4 | template: '#statisticLog', store,
5 | data: function () {
6 | return {
7 | api_name: null,
8 | total: null,
9 | apiData: {},
10 | logDialog: {
11 | menus: [],
12 | content: [],
13 | switch: false,
14 | }
15 | }
16 | },
17 | computed: {
18 | slideOpen() {
19 | return this.getSlideOpen();
20 | },
21 | },
22 | methods: {
23 | /*存到vuex map 方便调用store里函数*/
24 | ...Vuex.mapMutations(['setUserName', 'refreshJwtToken',]),
25 | ...Vuex.mapGetters(['username', 'jwtHeader', 'getSlideOpen']),
26 | queryData() {
27 | if (this.api_name !== null) {
28 | fetch('../wholog/query-api-data/?api_name=' + this.api_name, {
29 | method: 'get'
30 | }).then((response) => {
31 | return response.json();
32 | }).then((json) => {
33 | this.apiData = json['data'];
34 | if (json['status'] == "true") {
35 | console.log("重新开始draw")
36 | this.draw();
37 | } else {
38 | console.log(json['msg']);
39 | }
40 | }).catch((err) => {
41 | console.log(err)
42 | });
43 | } else {
44 | alert("请先输入要查询的内容");
45 | }
46 | },
47 | //echarts绘制方法
48 | draw() {
49 | // 指定图表的配置项和数据
50 | var option = {
51 | title: {
52 | text: "Api请求信息",
53 | subtext: "每个接口请求的统计"
54 | },
55 | tooltip: {
56 | trigger: "axis",
57 | formatter: (params) => {
58 | var result = '';
59 | params.forEach((item) => {
60 | result +=
61 | '' + "耗时:" + this.apiData.consume_time[item.dataIndex] + "ms" + '
' +
62 | '' + "用例名:" + this.apiData.case_name[item.dataIndex] + '
' +
63 | '' + "请求时间:" + this.apiData.create_time[item.dataIndex] + '
' +
64 | '' + "请求类型:" + this.apiData.request_type[item.dataIndex] + '
' +
65 | '' + "返回Code:" + this.apiData.response_code[item.dataIndex] + '
'
66 | ;
67 | });
68 | return result;
69 | }
70 | },
71 | legend: {
72 | data: ["耗时"]
73 | },
74 | toolbox: {
75 | show: true,
76 | feature: {
77 | mark: {
78 | show: true
79 | },
80 | dataView: {
81 | show: true,
82 | readOnly: true
83 | },
84 | magicType: {
85 | show: false,
86 | type: ["line", "bar", "stack", "tiled"]
87 | },
88 | restore: {
89 | show: true
90 | },
91 | saveAsImage: {
92 | show: true
93 | }
94 | }
95 | },
96 | calculable: true,
97 | xAxis: [
98 | {
99 | name: "运行次数",
100 | type: "category",
101 | boundaryGap: false,
102 | data: this.apiData.num,
103 | nameLocation: "end"
104 | }
105 | ],
106 | yAxis: [
107 | {
108 | name: "耗时",
109 | type: "value",
110 | axisLabel: {
111 | formatter: '{value} ms'
112 | }
113 | }
114 | ],
115 | series: [
116 | {
117 | name: "耗时",
118 | type: "line",
119 | smooth: true,
120 | itemStyle: {
121 | normal: {
122 | areaStyle: {
123 | type: "default"
124 | }
125 | }
126 | },
127 | data: this.apiData.consume_time
128 | }
129 | ]
130 | };
131 |
132 | // 使用刚指定的配置项和数据显示图表。
133 | this.myChart.setOption(option);
134 | },
135 |
136 |
137 | //todo 登录提示
138 | /*查询对应记录下的详细运行日志记录*/
139 | queryDetailData(logId) {
140 | /*对logId进行处理兼容es*/
141 | logId = logId.replace(/\-/g, "");
142 | fetch('../wholog/queryLogData',
143 | {
144 | method: 'POST',
145 | credentials: "same-origin",
146 | headers: {
147 | 'Accept': 'application/json, text/plain, */*',
148 | 'Content-Type': 'application/json',
149 | 'Authorization': "JWT " + this.jwtHeader()
150 | },
151 | body: JSON.stringify({logId: logId})
152 | }).then((response) => {
153 | /*判断请求状态码*/
154 | if (response.status !== 200) {
155 | if (response.status === 401) {
156 | this.openLoginPopup();
157 | /*判断未登录时 去打开登录提示*/
158 | } else {
159 | console.log("请求失败,状态码为:" + response.status);
160 | }
161 | return;
162 | } else {
163 | return response.json();
164 | }
165 | }).then((json) => {
166 | console.log("请求成功,打开dialog");
167 | this.logDialog.menus = json['data'];
168 | this.openDialog();
169 | }).catch((err) => {
170 | console.log("请求wholog/queryLogData出错:" + err);
171 | });
172 |
173 | }, /*queryDetailData end*/
174 |
175 | /*打开和关闭日志运行详情对话框*/
176 | openDialog() {
177 | this.logDialog.switch = true;
178 | },
179 | closeDialog() {
180 | this.logDialog.switch = false;
181 | },
182 |
183 | },
184 |
185 | watch: { //数据变化时自动重画,在控制台修改message,会自动重画
186 | message: () => {
187 |
188 | this.draw();
189 | }
190 | },
191 | mounted() {
192 | this.refreshJwtToken();
193 | this.$nextTick(() => {
194 | this.myChart = echarts.init(document.getElementById('main-chart')); //初始化echarts实例
195 | this.draw();
196 | this.myChart.on('click', (params) => {
197 | //打开对话框,查询数据
198 | this.openDialog();
199 | this.queryDetailData(this.apiData.log_id[params.dataIndex]);
200 | });
201 | })
202 | },
203 |
204 |
205 | };
206 |
207 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/static/arbiter/js/wholog/route.js:
--------------------------------------------------------------------------------
1 | const router = new VueRouter({
2 | mode: 'history',
3 | base: "/arbiter/wholog/",
4 | routes: [
5 |
6 | {
7 | path: '/index',
8 | name:'index',
9 | components: {rootView:historyLog},
10 | },
11 | {
12 | path: '/historyLog',
13 | name:'historyLog',
14 | components: {mainView:historyLog},
15 | },
16 | {
17 | path: '/statisticLog',
18 | name:'statisticLog',
19 | components: {mainView:statisticLog},
20 | },
21 |
22 | ]
23 | });
--------------------------------------------------------------------------------
/arbiter-web/arbiter/urls.py:
--------------------------------------------------------------------------------
1 | """
2 |
3 | The `urlpatterns` list routes URLs to views. For more information please see:
4 | https://docs.djangoproject.com/en/1.11/topics/http/urls/
5 | Examples:
6 | Function views
7 | 1. Add an import: from my_app import views
8 | 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
9 | Class-based views
10 | 1. Add an import: from other_app.views import Home
11 | 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
12 | Including another URLconf
13 | 1. Import the include() function: from django.conf.urls import url, include
14 | 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
15 | """
16 | from django.conf.urls import include, url
17 | from django.contrib import admin
18 |
19 | urlpatterns = [
20 | # url(r'^jet/', include('jet.urls', 'jet')), # Django JET URLS
21 | # url(r'^jet/dashboard/', include('jet.dashboard.urls', 'jet-dashboard')), # Django JET dashboard URLS
22 | url(r'^admin/', include(admin.site.urls)),
23 | url(r'^arbiter/wholog/', include("arbiter.wholog.urls", namespace="arbiter-wholog")),
24 | url(r'^arbiter/', include("arbiter.core.urls", namespace="arbiter")),
25 |
26 | ]
27 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/wholog/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuaFramework/cua-arbiter/61b2ea5d8b7c825b75d0f333d202e5703e0565a9/arbiter-web/arbiter/wholog/__init__.py
--------------------------------------------------------------------------------
/arbiter-web/arbiter/wholog/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | # Register your models here.
4 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/wholog/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class LogManageConfig(AppConfig):
5 | name = 'arbiter.wholog'
6 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/wholog/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 |
3 | # Create your models here.
4 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/wholog/templates/component/arbiter-header.vue:
--------------------------------------------------------------------------------
1 | {% verbatim %}
2 |
28 | {% endverbatim %}
--------------------------------------------------------------------------------
/arbiter-web/arbiter/wholog/templates/component/case-float-btn.vue:
--------------------------------------------------------------------------------
1 | {% verbatim %}
2 |
3 |
4 |
6 |
9 |
10 |
11 |
12 |
14 | {{ log }}
15 |
16 |
18 |
19 |
20 |
21 |
22 | {% endverbatim %}
--------------------------------------------------------------------------------
/arbiter-web/arbiter/wholog/templates/component/history-log.vue:
--------------------------------------------------------------------------------
1 | {% verbatim %}
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
12 |
14 |
15 |
17 |
19 |
20 |
21 |
22 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
33 |
34 |
35 |
36 |
37 | {{ props.row.log_id }}
38 |
39 |
40 | {{ props.row.case_name }}
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | {{ scope.row.task_name }}
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
83 | {{ item }}
84 |
85 |
86 |
87 |
88 |
89 | 请登录再操作
90 |
91 |
92 |
93 |
94 | {% endverbatim %}
--------------------------------------------------------------------------------
/arbiter-web/arbiter/wholog/templates/component/log-slide.vue:
--------------------------------------------------------------------------------
1 | {% verbatim %}
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | {% endverbatim %}
--------------------------------------------------------------------------------
/arbiter-web/arbiter/wholog/templates/component/menu-icon-button.vue:
--------------------------------------------------------------------------------
1 | {% verbatim %}
2 |
14 | {% endverbatim %}
--------------------------------------------------------------------------------
/arbiter-web/arbiter/wholog/templates/component/statistic-log.vue:
--------------------------------------------------------------------------------
1 | {% verbatim %}
2 |
3 |
4 |
5 |
7 |
9 |
10 |
11 |
15 |
16 |
17 |
19 | {{ item }}
20 |
21 |
22 |
23 |
24 |
25 |
26 | {% endverbatim %}
--------------------------------------------------------------------------------
/arbiter-web/arbiter/wholog/templates/component/user-avatar.vue:
--------------------------------------------------------------------------------
1 | {% verbatim %}
2 |
3 |
4 | {{ usernameAbbreviation }}
6 |
7 |
10 |
11 |
12 |
13 |
14 |
16 |
17 |
18 |
19 |
20 | {% endverbatim %}
21 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/wholog/templates/index.html:
--------------------------------------------------------------------------------
1 | {% load static %}
2 | {% load i18n %}
3 | {% load staticfiles %}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | 日志查询
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | {% block head %}
22 | {% endblock head %}
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | {% verbatim %}
34 |
47 | {% endverbatim %}
48 | {% include "component/menu-icon-button.vue" %}
49 | {% include "component/user-avatar.vue" %}
50 | {% include "component/history-log.vue" %}
51 | {% include "component/statistic-log.vue" %}
52 | {% include "component/arbiter-header.vue" %}
53 | {% include "component/log-slide.vue" %}
54 |
55 | {% include "component/case-float-btn.vue" %}
56 |
57 |
58 |
59 |
60 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/wholog/tests.py:
--------------------------------------------------------------------------------
1 | import time
2 | from arbiter.common import utils
3 |
4 |
5 | # Create your tests here.
6 | class Test:
7 | def test_test(self):
8 | log_id = utils.generate_id()
9 | print(log_id)
10 |
11 | def test_time(self):
12 | t1 = time.time()
13 | print(t1)
14 | print(t1 * 10000000)
15 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/wholog/urls.py:
--------------------------------------------------------------------------------
1 | from django.conf.urls import url
2 |
3 | from . import views
4 |
5 | urlpatterns = [
6 | url(r'^query-api-data', views.query_api_data, name='query-api-data'),
7 | url(r'^api-count', views.api_count, name='api-count'),
8 | url(r'^getAllLog', views.get_all_log, name='getAllLog'),
9 | url(r'^deleteLog', views.delete_log, name='deleteLog'),
10 | # todo 登录登出抽离出来,现在core和wholog下的view均有
11 | url(r'^getUserDetail', views.auth_restful.get_user_detail, name='getUserDetail'),
12 | url(r'^queryLogData', views.queryLogData, name='queryLogData'),
13 | url(r'^home', views.home, name='home'),
14 | url(r'^index', views.index, name='index'),
15 | url(r'^.*$', views.index),
16 |
17 | ]
18 |
--------------------------------------------------------------------------------
/arbiter-web/arbiter/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for arbiter project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "arbiter.settings")
15 | application = get_wsgi_application()
16 |
--------------------------------------------------------------------------------
/arbiter-web/config.py:
--------------------------------------------------------------------------------
1 | arbiter_prod_config = \
2 | dict(redis_host='10.104.102.142',
3 | redis_port=6379,
4 | redis_dj_db=13,
5 | redis_arbiter_db=9,
6 | redis_elk_db=11,
7 | pgsql_host='10.104.104.39',
8 | pgsql_port='5432',
9 | pgsql_dbname='arbiter_dj',
10 | pgsql_user='luna',
11 | pgsql_password='luna',
12 | elk_url='10.104.104.57:9200',
13 | case_path='caseobj/case')
14 |
15 | arbiter_docker_config = \
16 | dict(redis_host='redis',
17 | redis_port=6379,
18 | redis_dj_db=3,
19 | redis_arbiter_db=9,
20 | redis_elk_db=11,
21 | pgsql_host='pgdb',
22 | pgsql_port='5432',
23 | pgsql_user='luna',
24 | pgsql_dbname='arbiter_dj',
25 | pgsql_password='luna',
26 | elk_url='elk:9200',
27 | case_path='caseobj/case')
28 |
--------------------------------------------------------------------------------
/arbiter-web/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | web:
4 | image: shimine/cua-arbiter-alpine
5 | ports:
6 | - "8000:8000"
7 | depends_on:
8 | - db
9 | command: python ./manage.py makemigrations arbiter&& python ./manage.py migrate && python ./manage.py shell < initadmin.py
10 |
11 | db:
12 | image: postgres
13 | ports:
14 | - "5432:5432"
15 | environment:
16 | - POSTGRES_PASSWORD=123456
17 | - POSTGRES_DB=arbiter_dj
18 | - POSTGRES_USER=luna
19 | - POSTGRES_PASSWORD=luna
20 |
21 | redis:
22 | image: redis
23 |
24 | elk:
25 | image: shimine/cua-arbiter-elk
26 | ports:
27 | - "5601:5601"
28 | - "9200:9200"
29 | - "5044:5044"
30 |
--------------------------------------------------------------------------------
/arbiter-web/docker_start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | python ./manage.py makemigrations arbiter&& python ./manage.py migrate && python ./manage.py shell < initadmin.py && python ./manage.py runserver 0.0.0.0:8000
--------------------------------------------------------------------------------
/arbiter-web/initadmin.py:
--------------------------------------------------------------------------------
1 | from django.contrib.auth.models import User
2 |
3 | # 如果没用用户 就新建一个
4 | if User.objects.count() == 0:
5 | User.objects.create_superuser('admin', 'admin@example.com', 'admin')
6 | else:
7 | print('Admin accounts can only be initialized if no Accounts exist. Now Accounts num is ' + str(
8 | User.objects.all().count()))
9 |
--------------------------------------------------------------------------------
/arbiter-web/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os
3 | import sys
4 |
5 | if __name__ == "__main__":
6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "arbiter.settings")
7 |
8 | try:
9 | from django.core.management import execute_from_command_line
10 | except ImportError:
11 | # The above import may fail for some other reason. Ensure that the
12 | # issue is really that Django is missing to avoid masking other
13 | # exceptions on Python 2.
14 | try:
15 | import django
16 | except ImportError:
17 | raise ImportError(
18 | "Couldn't import Django. Are you sure it's installed and "
19 | "available on your PYTHONPATH environment variable? Did you "
20 | "forget to activate a virtual environment?"
21 | )
22 | raise
23 | execute_from_command_line(sys.argv)
24 |
--------------------------------------------------------------------------------
/arbiter-web/requirements.txt:
--------------------------------------------------------------------------------
1 |
2 | ####### dj #######
3 | Django==1.11.15
4 | django-redis==4.8.0
5 | dj-database-url==0.4.2
6 | djangorestframework-jwt==1.11.0
7 | djangorestframework==3.7.3
8 | channels==1.1.8
9 | Twisted[tls,http2]==17.9.0
10 | ####### db #######
11 | psycopg2==2.7.3.2
12 | asgi_redis==1.4.3
13 | redis==2.10.6
14 | ####### elk #######
15 | elasticsearch==5.4.0
16 | ####### git #######
17 | gitpython==2.1.7
18 | ####### for tests #######
19 | requests==2.20.0
20 | bs4==0.0.1
21 | lxml==4.1.0
22 | nose==1.3.7
23 | ######others#######
24 | bleach>=2.1.3
25 | Markdown==2.6.9
26 | cloudinary==1.8.0
27 | cryptography==2.3
28 |
--------------------------------------------------------------------------------
/arbiter-web/stack-fix.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | typedef int (*func_t)(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg);
6 |
7 | int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg) {
8 |
9 | pthread_attr_t local;
10 | int used = 0, ret;
11 |
12 | if (!attr) {
13 | used = 1;
14 | pthread_attr_init(&local);
15 | attr = &local;
16 | }
17 | pthread_attr_setstacksize((void*)attr, 2 * 1024 * 1024); // 2 MB
18 |
19 | func_t orig = (func_t)dlsym(RTLD_NEXT, "pthread_create");
20 |
21 | ret = orig(thread, attr, start_routine, arg);
22 |
23 | if (used) {
24 | pthread_attr_destroy(&local);
25 | }
26 |
27 | return ret;
28 | }
--------------------------------------------------------------------------------
/doc/.gitignore:
--------------------------------------------------------------------------------
1 | # Eclipse Project Files #
2 |
3 | .classpath
4 | .project
5 | .settings
6 |
7 | # IntelliJ IDEA Files #
8 |
9 | *.iml
10 | *.ipr
11 | *.iws
12 | *.idea
13 |
--------------------------------------------------------------------------------
/doc/import.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuaFramework/cua-arbiter/61b2ea5d8b7c825b75d0f333d202e5703e0565a9/doc/import.gif
--------------------------------------------------------------------------------
/tasks.todo:
--------------------------------------------------------------------------------
1 | cua-arbiter里程碑:
2 | cua-arbiter_v1.0:
3 | ✔ 权限管理
4 | ✔ 用例页面展示
5 | ✔ 用例脚本页面编辑
6 | ✔ 执行用例脚本
7 |
8 | cua-arbiter_v1.5:
9 | ✔ 使用 muse-ui 前端重构
10 |
11 | cua-arbiter_v2.0:
12 | ✔ 用例脚本与GIT仓库同步(增/删/改)
13 | ✔ 用例批量执行(任务执行)
14 | ✔ 管理历史日志记录(删/查)
15 | ✔ 历史任务重新执行
16 | ☐ 根据历史日志生成图表
17 | ☐ 报告输出(pdf/html/email)
18 |
19 | backlog:
20 | ☐ 用例列表增量修改
21 | ☐ 细化权限管理(按钮权限与用例状态&登陆角色关联)
22 | ☐ 需求/项目管理
23 | ☐ checkList管理
24 | ☐ 需求-checkList关联
25 | ☐ 需求-用例脚本关联
--------------------------------------------------------------------------------