Merge pull request #152 from getrebuild/ntext-md-545

Fixs some styles
This commit is contained in:
RB 2020-03-30 21:07:58 +08:00 committed by GitHub
commit b8b4e500a3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
37 changed files with 328 additions and 241 deletions

View file

@ -157,7 +157,7 @@ public abstract class ChartData extends SetUser<ChartData> implements ChartSpec
private Field getField(JSONObject item) {
String field = item.getString("field");
if (!getSourceEntity().containsField(field)) {
throw new ChartsException("字段 [" + field.toUpperCase() + " ] 已被删除");
throw new ChartsException("字段 [" + field.toUpperCase() + " ] 已被删除,请调整图表配置");
}
return getSourceEntity().getField(field);
}

View file

@ -162,7 +162,7 @@ public class FeedsHelper {
/**
* URL 提取
*/
public static final Pattern URL_PATTERN = Pattern.compile("((www|https?:\\/\\/)[-a-zA-Z0-9+&@#/%?=~_|!:,.;]{5,300})");
public static final Pattern URL_PATTERN = Pattern.compile("((www|https?://)[-a-zA-Z0-9+&@#/%?=~_|!:,.;]{5,300})");
/**
* 格式化动态内容
@ -202,7 +202,8 @@ public class FeedsHelper {
ID user = ID.valueOf(at.substring(1));
if (user.getEntityCode() == EntityHelper.User && Application.getUserStore().existsUser(user)) {
String fullName = Application.getUserStore().getUser(user).getFullName();
content = content.replace(at, String.format("<a data-id=\"%s\">@%s</a>", user, fullName));
content = content.replace(at,
String.format("<a data-id=\"%s\">@%s</a>", user, fullName));
}
}

View file

@ -1,19 +1,8 @@
/*
rebuild - Building your business-systems freely.
Copyright (C) 2019 devezhao <zhaofang123@gmail.com>
Copyright (c) REBUILD <https://getrebuild.com/> and its owners. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
rebuild is dual-licensed under commercial and open source licenses (GPLv3).
See LICENSE and COMMERCIAL in the project root for license information.
*/
package com.rebuild.server.business.rbstore;
@ -103,7 +92,8 @@ public class MetaSchemaGenerator {
}
schemaEntity.put("fields", metaFields);
// 布局相关仅管理员
// 布局相关仅管理员的
JSONObject putLayouts = new JSONObject();
Object[][] layouts = Application.createQueryNoFilter(
"select applyType,config from LayoutConfig where belongEntity = ? and createdBy = ?")
@ -119,13 +109,14 @@ public class MetaSchemaGenerator {
}
schemaEntity.put("layouts", putLayouts);
// 过滤器仅管理员
// 过滤器仅管理员的
JSONObject putFilters = new JSONObject();
Object[][] filters = Application.createQueryNoFilter(
"select filterName,config from FilterConfig where belongEntity = ? and createdBy = ?")
.setParameter(1, entity.getName())
.setParameter(2, UserService.ADMIN_USER)
.array();
JSONObject putFilters = new JSONObject();
for (Object[] filter : filters) {
String name = (String) filter[0];
JSONObject config = JSON.parseObject((String) filter[1]);
@ -134,7 +125,7 @@ public class MetaSchemaGenerator {
}
}
schemaEntity.put("filters", putFilters);
return schemaEntity;
}

View file

@ -1,19 +1,8 @@
/*
rebuild - Building your business-systems freely.
Copyright (C) 2019 devezhao <zhaofang123@gmail.com>
Copyright (c) REBUILD <https://getrebuild.com/> and its owners. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
rebuild is dual-licensed under commercial and open source licenses (GPLv3).
See LICENSE and COMMERCIAL in the project root for license information.
*/
package com.rebuild.server.business.rbstore;
@ -40,10 +29,9 @@ public class RBStore {
private static final Log LOG = LogFactory.getLog(RBStore.class);
/**
* RB 仓库地址
* 源地址https://raw.githubusercontent.com/getrebuild/rebuild-datas/master/
* RB 仓库地址 https://github.com/getrebuild/rebuild-datas/
*/
public static final String DATA_REPO = "https://cdn.jsdelivr.net/gh/getrebuild/rebuild-datas/";
private static final String DATA_REPO = "https://getrebuild.com/gh/getrebuild/rebuild-datas/";
/**
* for Classification

View file

@ -44,7 +44,7 @@ public class SendNotification implements TriggerAction {
private static final Log LOG = LogFactory.getLog(SendNotification.class);
// 内部消息
// 通知
@SuppressWarnings("unused")
private static final int TYPE_NOTIFICATION = 1;
// 邮件

View file

@ -74,17 +74,17 @@ public class AesPreferencesConfigurer extends PreferencesPlaceholderConfigurer i
}
}
// PRIVATE
// SPEC MYSQL PORT
String mysqlPort = System.getProperty("mysql.port");
if (StringUtils.isNotBlank(mysqlPort)) {
String dbUrl = props.getProperty("db.url");
dbUrl = dbUrl.replace("3306", "4653");
dbUrl = dbUrl.replace("3306", mysqlPort);
props.put("db.url", dbUrl);
}
// MUST NOT BE NULL
setIfEmpty(props, ConfigurableItem.CacheHost, "127.0.0.1");
setIfEmpty(props, ConfigurableItem.CachePort, "16379");
setIfEmpty(props, ConfigurableItem.CachePort, "6379");
propsHold = (Properties) props.clone();

View file

@ -351,7 +351,7 @@ public class EasyMeta implements BaseMeta {
* @return
*/
public static String getLabel(BaseMeta meta) {
return meta.getDescription();
return StringUtils.defaultIfBlank(meta.getDescription(), meta.getName().toUpperCase());
}
/**

View file

@ -100,7 +100,7 @@ public class MessageBuilder {
* @param md2html
* @param xss
* @return
* @see MarkdownUtils#parse(String)
* @see MarkdownUtils#render(String)
*/
public static String formatMessage(String message, boolean md2html, boolean xss) {
if (xss) {
@ -111,14 +111,14 @@ public class MessageBuilder {
Matcher atMatcher = AT_PATTERN.matcher(message);
while (atMatcher.find()) {
String at = atMatcher.group();
String atLabel = parseAtsId(at.substring(1));
String atLabel = parseAtId(at.substring(1));
if (atLabel != null && !atLabel.equals(at)) {
message = message.replace(at, atLabel);
}
}
if (md2html) {
message = MarkdownUtils.parse(message);
message = MarkdownUtils.render(message);
}
return message;
}
@ -127,7 +127,7 @@ public class MessageBuilder {
* @param atid
* @return
*/
protected static String parseAtsId(String atid) {
protected static String parseAtId(String atid) {
if (!ID.isId(atid)) {
return atid;
}

View file

@ -265,7 +265,8 @@ public class CommonsUtils {
if (text == null || StringUtils.isBlank(text.toString())) {
return StringUtils.EMPTY;
}
return StringEscapeUtils.escapeHtml(text.toString());
String escape = StringEscapeUtils.escapeHtml(text.toString());
return escape.replace("&gt;", ">"); // `>` for MD
}
/**

View file

@ -1,19 +1,8 @@
/*
rebuild - Building your business-systems freely.
Copyright (C) 2019 devezhao <zhaofang123@gmail.com>
Copyright (c) REBUILD <https://getrebuild.com/> and its owners. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
rebuild is dual-licensed under commercial and open source licenses (GPLv3).
See LICENSE and COMMERCIAL in the project root for license information.
*/
package com.rebuild.utils;
@ -43,10 +32,12 @@ public class MarkdownUtils {
private static final HtmlRenderer RENDERER = HtmlRenderer.builder(OPTIONS).build();
/**
* MD 渲染支持表格
*
* @param md
* @return
*/
public static String parse(String md) {
public static String render(String md) {
Node document = PARSER.parse(md);
return RENDERER.render(document);
}

View file

@ -87,6 +87,7 @@ public class FileManagerControll extends BaseControll {
willDeletes.add(fileId);
}
Application.getCommonService().delete(willDeletes.toArray(new ID[0]));
writeSuccess(response);
}

View file

@ -1,6 +1,8 @@
-- !!! NOTICE !!!
-- IF YOU USING MYSQL 5.7 OR ABOVE, YOU SHOULD REMOVED THESE SQL_MODES IN my.cnf/my.ini FIRST.
-- !!! MYSQL VERSION NOTICE !!!
-- IN 5.7 OR ABOVE, YOU SHOULD REMOVED THESE SQL_MODES IN my.cnf/my.ini FIRST.
-- ONLY_FULL_GROUP_BY
-- IN 8.0 OR ABOVE, ONLY SUPPORTS mysql_native_password AUTHENTICATION MODE
-- default_authentication_plugin=mysql_native_password
-- #1 database/user
-- 首次使用请移除以下注释以创建数据库和用户

View file

@ -7,7 +7,7 @@
<script src="${baseUrl}/assets/lib/widget/bootstrap-datetimepicker.min.js"></script>
<script src="${baseUrl}/assets/lib/jquery.html5uploader.js"></script>
<script src="${baseUrl}/assets/lib/qiniu.min.js"></script>
<script src="${baseUrl}/assets/lib/widget/select2.min.js"></script>
<script src="${baseUrl}/assets/lib/widget/select2.min.js?v=4.0.13"></script>
<script src="${baseUrl}/assets/lib/jquery-ui.min.js"></script>
<script src="${baseUrl}/assets/lib/react/babel.js?v=6.26.0"></script>
<script src="${baseUrl}/assets/lib/react/react.development.js?v=16.10.2"></script>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" type="text/css" href="${baseUrl}/assets/lib/widget/perfect-scrollbar.min.css">
<link rel="stylesheet" type="text/css" href="${baseUrl}/assets/lib/widget/bootstrap-datetimepicker.min.css">
<link rel="stylesheet" type="text/css" href="${baseUrl}/assets/lib/animate.min.css">
<link rel="stylesheet" type="text/css" href="${baseUrl}/assets/lib/widget/select2.min.css">
<link rel="stylesheet" type="text/css" href="${baseUrl}/assets/lib/widget/select2.min.css?v=4.0.13">
<link rel="stylesheet" type="text/css" href="${baseUrl}/assets/lib/widget/mprogress.min.css">
<link rel="stylesheet" type="text/css" href="${baseUrl}/assets/lib/jquery-ui.min.css">
<link rel="stylesheet" type="text/css" href="${baseUrl}/assets/css/rb-base.css">

View file

@ -12067,7 +12067,7 @@ canvas {
}
.rb-icons-nav>li.dropdown>a .indicator,
.unread-flag {
.indicator-primary {
background-color: #4285f4;
border-radius: 50%;
display: block;

View file

@ -35,6 +35,7 @@ body {
box-shadow: 0 3px .3077rem rgba(0, 0, 0, .1);
border-width: 0;
border-radius: 0;
max-width: 300px;
}
.dropdown-menu.primary>.dropdown-item:hover,
@ -315,8 +316,8 @@ a.btn {
display: block;
}
.rb-color-header .dropdown .icon {
color: #fff !important;
.rb-color-header .dropdown > a > .icon {
color: #fff;
}
.logo-img {
@ -385,6 +386,11 @@ a.btn {
color: #737373;
}
.adv-search button .indicator-primary {
top: 3px;
right: 3px;
}
.input-search .input-group-btn.plus {
margin-right: -36px;
margin-top: -1px;
@ -1193,7 +1199,7 @@ i.split.ui-draggable-dragging {
}
.data-list .table tbody tr td.user-avatar {
padding: 6px 10px;
padding: 3px 10px;
}
.data-list .table tbody tr td.user-avatar img {
@ -1430,6 +1436,10 @@ th.column-fixed {
.main-content>.nav-tabs-classic>li.nav-item a.nav-link {
padding: 11px 15px;
min-width: 101px;
max-width: 245px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.sortable-box-title {
@ -1754,6 +1764,7 @@ th.column-fixed {
.adv-search .dropdown-item div.action a:hover {
color: #4285f4 !important;
background-color: rgba(0, 0, 0, 0.05);
}
/* AdvFilter */
@ -1922,6 +1933,8 @@ div.dataTables_wrapper div.paging_sizes select {
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 100%;
text-align: center;
}
.zicon,
@ -2663,6 +2676,11 @@ form {
padding-left: 18px;
}
.notification-list .notification.focus {
outline: 2px solid #fbbc05;
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, .1);
}
.select2-sm .select2-container--default .select2-selection--single,
.select2-sm .select2-container--default .select2-selection--multiple {
min-height: 36px;
@ -3381,4 +3399,28 @@ a.icon-link>.zmdi {
.btn {
min-width: 88px;
}
}
.mr-zero {
margin-right: -15px;
}
.ml-zero {
margin-left: -15px;
}
/* text overflow */
.aside-header .title,
.dept-tree ul li a,
.dropdown-item,
.modal-header .modal-title,
.view-header .title {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.nav-tabs>li.nav-item a.nav-link {
max-width: 200px;
}

View file

@ -46,7 +46,8 @@ body {
display: inline-block;
margin: 0;
font-weight: 300;
font-size: 1.538rem
font-size: 1.538rem;
max-width: 80%;
}
.view-header>span>.close {
@ -96,7 +97,6 @@ body {
.nav-tabs>li.nav-item a.nav-link {
padding: 11px 10px;
max-width: 130px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;

View file

@ -7,10 +7,10 @@ See LICENSE and COMMERCIAL in the project root for license information.
/* eslint-disable react/no-string-refs */
const wpc = window.__PageConfig
let esourceFilter
$(document).ready(() => {
$(window).trigger('resize')
//$('.navbar-brand').attr('href', 'javascript:;')
$('.chart-type>a, .chart-option .zicon').tooltip({ html: true, container: '.config-aside' })
if (wpc.chartOwningAdmin !== true) $('.admin-show').remove()
@ -52,7 +52,7 @@ $(document).ready(() => {
}
}).disableSelection()
let saveFilter = function (filter) {
const saveFilter = function (filter) {
esourceFilter = filter
render_preview()
}
@ -60,25 +60,31 @@ $(document).ready(() => {
renderRbcomp(<AdvFilter title="设置过滤条件" entity={wpc.sourceEntity} filter={esourceFilter} inModal={true} confirm={saveFilter} canNoFilters={true} />)
})
let cts = $('.chart-type > a').click(function () {
let _this = $(this)
if (_this.hasClass('active') === false) return
const cts = $('.chart-type > a').click(function () {
const $this = $(this)
if ($this.hasClass('active') === false) return
cts.removeClass('select')
_this.addClass('select')
$this.addClass('select')
render_option()
})
$('.chart-option .custom-control').click(function () {
render_option()
})
//
$('.rb-toggle-left-sidebar').attr('title', '完成').off('click').on('click', () => {
let cfg = build_config()
const cfg = build_config()
if (!cfg) { RbHighbar.create('当前图表无数据'); return }
let _data = { config: JSON.stringify(cfg), title: cfg.title, belongEntity: cfg.entity, chartType: cfg.type }
_data.metadata = { entity: 'ChartConfig', id: wpc.chartId }
const data = {
config: JSON.stringify(cfg),
title: cfg.title,
belongEntity: cfg.entity,
chartType: cfg.type,
metadata: { entity: 'ChartConfig', id: wpc.chartId }
}
let dash = $urlp('dashid') || ''
$.post('/dashboard/chart-save?dashid=' + dash, JSON.stringify(_data), function (res) {
const dash = $urlp('dashid') || ''
$.post(`/dashboard/chart-save?dashid=${dash}`, JSON.stringify(data), function (res) {
if (res.error_code === 0) {
wpc.chartConfig = cfg
location.href = (dash ? ('home?d=' + dash) : 'home') + '#' + res.data.id
@ -88,26 +94,27 @@ $(document).ready(() => {
}).tooltip({ placement: 'right' }).find('.zmdi').addClass('zmdi-arrow-left')
if (wpc.chartConfig && wpc.chartConfig.axis) {
$(wpc.chartConfig.axis.dimension).each((idx, item) => { add_axis('.J_axis-dim', item) })
$(wpc.chartConfig.axis.numerical).each((idx, item) => { add_axis('.J_axis-num', item) })
$(wpc.chartConfig.axis.dimension).each((idx, item) => add_axis('.J_axis-dim', item))
$(wpc.chartConfig.axis.numerical).each((idx, item) => add_axis('.J_axis-num', item))
$('.chart-type>a[data-type="' + wpc.chartConfig.type + '"]').trigger('click')
esourceFilter = wpc.chartConfig.filter
let option = wpc.chartConfig.option || {}
const option = wpc.chartConfig.option || {}
for (let k in option) {
let opt = $('.chart-option input[data-name=' + k + ']')
const opt = $('.chart-option input[data-name=' + k + ']')
if (opt.length > 0) {
if (opt.attr('type') === 'checkbox') {
if (option[k] === 'true') opt.trigger('click')
if (option[k] === 'true' || option[k] === true) opt.trigger('click')
} else {
opt.val(option[k])
}
else opt.val(option[k])
}
}
}
if (!wpc.chartId) $('<h4 class="chart-undata must-center">当前图表无数据</h4>').appendTo('#chart-preview')
window.onbeforeunload = function () {
let ccfg = build_config()
const ccfg = build_config()
if (!ccfg && !wpc.chartId); // New and unconfig
else if (JSON.stringify(ccfg) === JSON.stringify(wpc.chartConfig)); // Unchanged
else return false
@ -121,18 +128,19 @@ $(document).ready(() => {
const CTs = { SUM: '求和', AVG: '平均值', MAX: '最大值', MIN: '最小值', COUNT: '计数', Y: '按年', Q: '按季', M: '按月', D: '按日', H: '按时' }
let dlgAxisProps
let add_axis = ((target, axis) => {
let el = $($('#axis-ietm').html()).appendTo($(target))
//
const add_axis = ((target, axis) => {
const el = $($('#axis-ietm').html()).appendTo($(target))
let fName = null
let fLabel = null
let fType = null
let calc = null
let sort = null
let isNumAxis = $(target).hasClass('J_axis-num')
const isNumAxis = $(target).hasClass('J_axis-num')
// in-load
if (axis.field) {
let field = $('.fields [data-field="' + axis.field + '"]')
const field = $('.fields [data-field="' + axis.field + '"]')
fName = axis.field
fLabel = field.text()
fType = field.data('type')
@ -162,25 +170,26 @@ let add_axis = ((target, axis) => {
if (fType === 'date') el.find('.J_text, .J_num').remove()
else el.find('.J_text, .J_num, .J_date, .dropdown-divider').remove()
}
let aopts = el.find('.dropdown-menu .dropdown-item').click(function () {
let _this = $(this)
if (_this.hasClass('disabled') || _this.parent().hasClass('disabled')) return false
let calc = _this.data('calc')
let sort = _this.data('sort')
const aopts = el.find('.dropdown-menu .dropdown-item').click(function () {
const $this = $(this)
if ($this.hasClass('disabled') || $this.parent().hasClass('disabled')) return false
const calc = $this.data('calc')
const sort = $this.data('sort')
if (calc) {
el.find('span').text(fLabel + (' (' + _this.text() + ')'))
el.find('span').text(fLabel + (' (' + $this.text() + ')'))
el.attr('data-calc', calc)
aopts.each(function () { if ($(this).data('calc')) $(this).removeClass('text-primary') })
_this.addClass('text-primary')
$this.addClass('text-primary')
render_preview()
} else if (sort) {
el.attr('data-sort', sort)
aopts.each(function () { if ($(this).data('sort')) $(this).removeClass('text-primary') })
_this.addClass('text-primary')
$this.addClass('text-primary')
render_preview()
} else {
let state = { isNumAxis: isNumAxis, label: el.attr('data-label'), scale: el.attr('data-scale') }
const state = { isNumAxis: isNumAxis, label: el.attr('data-label'), scale: el.attr('data-scale') }
state.callback = (s) => {
el.attr({ 'data-label': s.label, 'data-scale': s.scale })
render_preview()
@ -194,7 +203,7 @@ let add_axis = ((target, axis) => {
if (sort) el.find('.dropdown-menu li[data-sort="' + sort + '"]').addClass('text-primary')
el.attr({ 'data-type': fType, 'data-field': fName })
el.find('span').text(fLabel + (calc ? (' (' + CTs[calc] + ')') : ''))
el.find('span').text(fLabel + (calc ? ` (${CTs[calc]})` : ''))
el.find('a.del').click(() => {
el.remove()
render_option()
@ -203,16 +212,16 @@ let add_axis = ((target, axis) => {
})
//
let render_option = (() => {
let cts = $('.chart-type>a').removeClass('active')
let dimsAxis = $('.J_axis-dim .item').length
let numsAxis = $('.J_axis-num .item').length
const render_option = (() => {
const cts = $('.chart-type>a').removeClass('active')
const dimsAxis = $('.J_axis-dim .item').length
const numsAxis = $('.J_axis-num .item').length
cts.each(function () {
let _this = $(this)
let dims = (_this.data('allow-dims') || '0|0').split('|')
let nums = (_this.data('allow-nums') || '0|0').split('|')
if (dimsAxis >= ~~dims[0] && dimsAxis <= ~~dims[1] && numsAxis >= ~~nums[0] && numsAxis <= ~~nums[1]) _this.addClass('active')
const $this = $(this)
const dims = ($this.data('allow-dims') || '0|0').split('|')
const nums = ($this.data('allow-nums') || '0|0').split('|')
if (dimsAxis >= ~~dims[0] && dimsAxis <= ~~dims[1] && numsAxis >= ~~nums[0] && numsAxis <= ~~nums[1]) $this.addClass('active')
})
// FUNNEL
if ((dimsAxis === 1 && numsAxis === 1) || (dimsAxis === 0 && numsAxis > 1));
@ -227,14 +236,15 @@ let render_option = (() => {
const ct = select.data('type')
// Option
$('.chart-option>div').addClass('hide')
let ctOpt = $('.J_opt-' + ct)
const ctOpt = $('.J_opt-' + ct)
if (ctOpt.length === 0) $('.J_opt-UNDEF').removeClass('hide')
else ctOpt.removeClass('hide')
// Sort
let sorts = $('.axis-editor .J_sort').removeClass('disabled')
if (ct === 'INDEX') sorts.addClass('disabled')
else if (ct === 'FUNNEL') {
const sorts = $('.axis-editor .J_sort').removeClass('disabled')
if (ct === 'INDEX') {
sorts.addClass('disabled')
} else if (ct === 'FUNNEL') {
if (numsAxis >= 1 && dimsAxis >= 1) $('.J_numerical .J_sort').addClass('disabled')
else sorts.addClass('disabled')
}
@ -244,14 +254,14 @@ let render_option = (() => {
//
let render_preview_chart = null
let render_preview = (() => {
const render_preview = (() => {
$setTimeout(() => {
if (render_preview_chart) {
ReactDOM.unmountComponentAtNode(document.getElementById('chart-preview'))
render_preview_chart = null
}
let cfg = build_config()
const cfg = build_config()
if (!cfg) {
$('#chart-preview').html('<h4 class="chart-undata must-center">当前图表无数据</h4>')
return
@ -259,28 +269,29 @@ let render_preview = (() => {
$('#chart-preview').empty()
// eslint-disable-next-line no-undef
let c = detectChart(cfg)
const c = detectChart(cfg)
if (c) renderRbcomp(c, 'chart-preview', function () { render_preview_chart = this })
else $('#chart-preview').html('<h4 class="chart-undata must-center">不支持的图表类型</h4>')
}, 400, 'chart-preview')
})
let build_config = (() => {
let cfg = { entity: wpc.sourceEntity, title: $val('#chart-title') || '未命名图表' }
//
const build_config = (() => {
const cfg = { entity: wpc.sourceEntity, title: $val('#chart-title') || '未命名图表' }
cfg.type = $('.chart-type>a.select').data('type')
if (!cfg.type) return
let dims = []
let nums = []
$('.J_axis-dim>span').each((idx, item) => { dims.push(__build_axisItem(item, false)) })
$('.J_axis-num>span').each((idx, item) => { nums.push(__build_axisItem(item, true)) })
const dims = []
const nums = []
$('.J_axis-dim>span').each((idx, item) => dims.push(__buildAxisItem(item, false)))
$('.J_axis-num>span').each((idx, item) => nums.push(__buildAxisItem(item, true)))
if (dims.length === 0 && nums.length === 0) return
cfg.axis = { dimension: dims, numerical: nums }
let opts = {}
$('.chart-option>div.active input').each(function () {
let name = $(this).data('name')
const opts = {}
$('.chart-option input').each(function () {
const name = $(this).data('name')
if (name) opts[name] = $val(this)
})
cfg.option = opts
@ -290,9 +301,14 @@ let build_config = (() => {
if (rb.env === 'dev') console.log(cfg)
return cfg
})
let __build_axisItem = ((item, isNum) => {
const __buildAxisItem = ((item, isNum) => {
item = $(item)
let x = { field: item.data('field'), sort: item.attr('data-sort') || '', label: item.attr('data-label') || '' }
const x = {
field: item.data('field'),
sort: item.attr('data-sort') || '',
label: item.attr('data-label') || ''
}
if (isNum) {
x.calc = item.attr('data-calc')
x.scale = item.attr('data-scale')
@ -306,40 +322,44 @@ class DlgAxisProps extends RbFormHandler {
constructor(props) {
super(props)
}
render() {
return (<RbModal title="显示样式" ref={(c) => this._dlg = c}>
<div className="form">
<div className="form-group row">
<label className="col-sm-3 col-form-label text-sm-right">別名</label>
<div className="col-sm-7">
<input className="form-control form-control-sm" placeholder="默认" data-id="label" value={this.state.label || ''} onChange={this.handleChange} />
</div>
</div>
{this.state.isNumAxis !== true ? null :
return (
<RbModal title="显示样式" ref={(c) => this._dlg = c}>
<div className="form">
<div className="form-group row">
<label className="col-sm-3 col-form-label text-sm-right">小数位</label>
<label className="col-sm-3 col-form-label text-sm-right">別名</label>
<div className="col-sm-7">
<select className="form-control form-control-sm" value={this.state.scale || 2} data-id="scale" onChange={this.handleChange}>
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
</select>
<input className="form-control form-control-sm" placeholder="默认" data-id="label" value={this.state.label || ''} onChange={this.handleChange} />
</div>
</div>
}
<div className="form-group row footer">
<div className="col-sm-7 offset-sm-3">
<button className="btn btn-primary btn-space" type="button" onClick={() => this.saveProps()}>确定</button>
<a className="btn btn-link btn-space" onClick={() => this.hide()}>取消</a>
{this.state.isNumAxis !== true ? null :
<div className="form-group row">
<label className="col-sm-3 col-form-label text-sm-right">小数位</label>
<div className="col-sm-7">
<select className="form-control form-control-sm" value={this.state.scale || 2} data-id="scale" onChange={this.handleChange}>
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
</select>
</div>
</div>
}
<div className="form-group row footer">
<div className="col-sm-7 offset-sm-3">
<button className="btn btn-primary btn-space" type="button" onClick={() => this.saveProps()}>确定</button>
<a className="btn btn-link btn-space" onClick={() => this.hide()}>取消</a>
</div>
</div>
</div>
</div>
</RbModal>)
</RbModal>
)
}
saveProps() {
this.state.callback(this.state)
this.hide()

View file

@ -535,7 +535,7 @@ class FeedsSchedule extends BaseChart {
renderChart(data) {
const table = (!data || data.length === 0) ?
<div className="chart-undata must-center text-center"><i className="zmdi zmdi-check icon text-success"></i> 暂无待办日程<br />过期超过 30 天的日程将不再显示</div>
<div className="chart-undata must-center"><i className="zmdi zmdi-check icon text-success"></i> 暂无待办日程<br />过期超过 30 天的日程将不再显示</div>
:
<div>
<table className="table table-striped table-hover">

View file

@ -13,13 +13,14 @@ window.clickIcon = function (icon) {
}
const wpc = window.__PageConfig
$(document).ready(function () {
if (!wpc.metaId) $('.footer .alert').removeClass('hide')
else $('.footer .J_action').removeClass('hide')
$('.J_tab-' + wpc.entity + ' a').addClass('active')
let _btn = $('.J_save').click(function () {
const $btn = $('.J_save').click(function () {
if (!wpc.metaId) return
let _data = {
entityLabel: $val('#entityLabel'),
@ -33,7 +34,7 @@ $(document).ready(function () {
if (Object.keys(_data).length === 0) { location.reload(); return }
_data.metadata = { entity: 'MetaEntity', id: wpc.metaId }
_btn.button('loading')
$btn.button('loading')
$.post('../entity-update', JSON.stringify(_data), function (res) {
if (res.error_code === 0) location.reload()
else RbHighbar.error(res.error_msg)
@ -45,8 +46,8 @@ $(document).ready(function () {
})
$.get('/commons/metadata/fields?entity=' + wpc.entity, function (d) {
let rs = d.data.map((item) => {
let canName = item.type === 'NUMBER' || item.type === 'DECIMAL' ||
const rs = d.data.map((item) => {
const canName = item.type === 'NUMBER' || item.type === 'DECIMAL' ||
item.type === 'TEXT' || item.type === 'EMAIL' || item.type === 'URL' || item.type === 'PHONE' ||
item.type === 'SERIES' || item.type === 'PICKLIST' || item.type === 'CLASSIFICATION' ||
item.type === 'DATE' || item.type === 'DATETIME'
@ -54,7 +55,7 @@ $(document).ready(function () {
id: item.name,
text: item.label,
disabled: canName === false,
title: canName === false ? '此字段类型不支持作为名称字段使用' : ''
title: canName === false ? '此字段类型不支持作为名称字段使用' : item.label
}
})
let rsSort = []
@ -64,12 +65,11 @@ $(document).ready(function () {
rs.forEach((item) => {
if (item.disabled === true) rsSort.push(item)
})
rs = rsSort
$('#nameField').select2({
placeholder: '选择字段',
allowClear: false,
data: rs
data: rsSort
}).val(wpc.nameField).trigger('change')
})
})

View file

@ -442,7 +442,7 @@ function __renderRichContent(e) {
}
const ANN_OPTIONS = [[1, '动态页'], [2, '首页'], [4, '登录页']]
const REM_OPTIONS = [[1, '内部消息'], [2, '邮件']]
const REM_OPTIONS = [[1, '消息通知'], [2, '邮件']]
function __findMaskTexts(mask, options) {
const texts = []
options.forEach((item) => {

View file

@ -537,7 +537,7 @@ class ScheduleOptions extends React.Component {
<dd className="col-12 col-lg-9 mb-0" ref={(c) => this._scheduleRemind = c}>
<label className="custom-control custom-checkbox custom-control-inline">
<input className="custom-control-input" name="showOn" type="checkbox" value={1} disabled={this.props.readonly} />
<span className="custom-control-label">内部消息</span>
<span className="custom-control-label">消息通知</span>
</label>
<label className="custom-control custom-checkbox custom-control-inline">
<input className="custom-control-input" name="showOn" type="checkbox" value={2} disabled={this.props.readonly} />
@ -608,6 +608,7 @@ class FeedsEditDlg extends RbModalHandler {
_post = () => {
const _data = this._editor.vals()
if (!_data) return
if (!_data.content) { RbHighbar.create('请输入动态内容'); return }
_data.metadata = { entity: 'Feeds', id: this.props.id }

View file

@ -8,7 +8,7 @@ See LICENSE and COMMERCIAL in the project root for license information.
// ~~ /
const TYPE_DOCS = ['.doc', '.docx', '.rtf', '.xls', '.xlsx', '.ppt', '.pptx', '.pdf']
const TYPE_TEXTS = ['.txt', '.xml', '.json', '.md', '.yml', '.css', '.js', '.htm', '.html']
const TYPE_TEXTS = ['.txt', '.xml', '.json', '.md', '.yml', '.css', '.js', '.htm', '.html', '.log', '.sql']
const TYPE_IMGS = ['.jpg', '.jpeg', '.gif', '.png', '.bmp']
const TYPE_AUDIOS = ['.mp3', '.wav', '.ogg', '.acc']
const TYPE_VIDEOS = ['.mp4', '.webm']
@ -94,7 +94,9 @@ class RbPreview extends React.Component {
renderText() {
return <div className="container fp-content">
<div className="iframe text" onClick={this.__stopEvent}>
{this.state.previewText ? <pre>{this.state.previewText}</pre> : <div className="must-center"><RbSpinner fully={true} /></div>}
{(this.state.previewText || this.state.previewText === '')
? <pre>{this.state.previewText || <i className="text-muted">无内容</i>}</pre>
: <div className="must-center"><RbSpinner fully={true} /></div>}
</div>
</div>
}

View file

@ -78,7 +78,7 @@ class FolderEditDlg extends RbFormHandler {
this.disabled(true)
$.post('/app/entity/record-save', JSON.stringify(_data), () => {
this.hide()
this.props.call && this.props.call()
typeof this.props.call === 'function' && this.props.call()
})
}
}
@ -347,8 +347,9 @@ $(document).ready(() => {
if (res.error_code === 0) {
this.hide()
filesList.loadData()
} RbHighbar.error(res.error_msg)
} else {
RbHighbar.error(res.error_msg)
}
})
}
})

View file

@ -64,13 +64,14 @@ class FilesList extends React.Component {
componentDidMount = () => this.loadData()
loadData(entry, pageNo) {
this.__lastEntry = entry = entry || this.__lastEntry
this.__lastEntry = entry || this.__lastEntry
this.__pageNo = pageNo || 1
$.get(`/files/list-file?entry=${entry}&sort=${currentSort || ''}&q=${$encode(currentSearch || '')}&pageNo=${this.__pageNo}&pageSize=${PAGE_SIZE}`, (res) => {
const _current = res.data || []
let _files = this.__pageNo === 1 ? [] : this.state.files
_files = [].concat(_files, _current)
this.setState({ files: _files, currentLen: _current.length })
const url = `/files/list-file?entry=${this.__lastEntry}&sort=${currentSort || ''}&q=${$encode(currentSearch || '')}&pageNo=${this.__pageNo}&pageSize=${PAGE_SIZE}`
$.get(url, (res) => {
const current = res.data || []
let files = this.__pageNo === 1 ? [] : this.state.files
files = [].concat(files, current)
this.setState({ files: files, currentLen: current.length })
})
}

View file

@ -5,6 +5,7 @@ rebuild is dual-licensed under commercial and open source licenses (GPLv3).
See LICENSE and COMMERCIAL in the project root for license information.
*/
let focusItem
$(document).ready(() => {
let mList = <MessageList lazy={true} />
if (window.__PageConfig && window.__PageConfig.type === 'Approval') mList = <ApprovalList />
@ -16,10 +17,11 @@ $(document).ready(() => {
mList.fetchList(1, $(this).data('type'))
})
let ntype = location.hash || '#unread'
ntype = $('.notification-type a[href="' + ntype + '"]')
if (ntype.length === 0) ntype = $('.notification-type a[href="#unread"]')
ntype.trigger('click')
const ntype = (location.hash || '#unread').split('=')
focusItem = ntype[1]
let activeNav = $('.notification-type a[href="' + ntype[0] + '"]')
if (ntype.length === 0) activeNav = $('.notification-type a[href="#unread"]')
activeNav.trigger('click')
})
//
@ -54,7 +56,7 @@ class MessageList extends React.Component {
if (item[3]) clazz += ' notification-unread'
if (append) clazz += ' append'
return <li className={clazz} key={item[4]} onClick={item[3] ? () => this.makeRead(item[4]) : null}>
return <li id={item[4]} className={`${clazz} ${item[4] === focusItem ? 'focus' : ''}`} key={item[4]} onClick={item[3] ? () => this.makeRead(item[4]) : null}>
<span className="a">
<div className="image"><img src={`${rb.baseUrl}/account/user-avatar/${item[0][0]}`} title={item[0][1]} alt="Avatar" /></div>
<div className="notification-info">
@ -90,6 +92,7 @@ class MessageList extends React.Component {
if (e && e.stopPropagation) e.stopPropagation()
})
setTimeout(() => $gotoSection(), 200)
focusItem = null
}
gotoPage(p) {

View file

@ -12,6 +12,9 @@ See LICENSE and COMMERCIAL in the project root for license information.
/*! https://github.com/gabceb/jquery-browser-plugin */
// eslint-disable-next-line
!function (a) { "function" == typeof define && define.amd ? define(["jquery"], function (b) { return a(b) }) : "object" == typeof module && "object" == typeof module.exports ? module.exports = a(require("jquery")) : a(window.jQuery) }(function (a) { "use strict"; function b(a) { void 0 === a && (a = window.navigator.userAgent), a = a.toLowerCase(); var b = /(edge)\/([\w.]+)/.exec(a) || /(opr)[\/]([\w.]+)/.exec(a) || /(chrome)[ \/]([\w.]+)/.exec(a) || /(iemobile)[\/]([\w.]+)/.exec(a) || /(version)(applewebkit)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(a) || /(webkit)[ \/]([\w.]+).*(version)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(a) || /(webkit)[ \/]([\w.]+)/.exec(a) || /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a) || /(msie) ([\w.]+)/.exec(a) || a.indexOf("trident") >= 0 && /(rv)(?::| )([\w.]+)/.exec(a) || a.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a) || [], c = /(ipad)/.exec(a) || /(ipod)/.exec(a) || /(windows phone)/.exec(a) || /(iphone)/.exec(a) || /(kindle)/.exec(a) || /(silk)/.exec(a) || /(android)/.exec(a) || /(win)/.exec(a) || /(mac)/.exec(a) || /(linux)/.exec(a) || /(cros)/.exec(a) || /(playbook)/.exec(a) || /(bb)/.exec(a) || /(blackberry)/.exec(a) || [], d = {}, e = { browser: b[5] || b[3] || b[1] || "", version: b[2] || b[4] || "0", versionNumber: b[4] || b[2] || "0", platform: c[0] || "" }; if (e.browser && (d[e.browser] = !0, d.version = e.version, d.versionNumber = parseInt(e.versionNumber, 10)), e.platform && (d[e.platform] = !0), (d.android || d.bb || d.blackberry || d.ipad || d.iphone || d.ipod || d.kindle || d.playbook || d.silk || d["windows phone"]) && (d.mobile = !0), (d.cros || d.mac || d.linux || d.win) && (d.desktop = !0), (d.chrome || d.opr || d.safari) && (d.webkit = !0), d.rv || d.iemobile) { var f = "msie"; e.browser = f, d[f] = !0 } if (d.edge) { delete d.edge; var g = "msedge"; e.browser = g, d[g] = !0 } if (d.safari && d.blackberry) { var h = "blackberry"; e.browser = h, d[h] = !0 } if (d.safari && d.playbook) { var i = "playbook"; e.browser = i, d[i] = !0 } if (d.bb) { var j = "blackberry"; e.browser = j, d[j] = !0 } if (d.opr) { var k = "opera"; e.browser = k, d[k] = !0 } if (d.safari && d.android) { var l = "android"; e.browser = l, d[l] = !0 } if (d.safari && d.kindle) { var m = "kindle"; e.browser = m, d[m] = !0 } if (d.safari && d.silk) { var n = "silk"; e.browser = n, d[n] = !0 } return d.name = e.browser, d.platform = e.platform, d } return window.jQBrowser = b(window.navigator.userAgent), window.jQBrowser.uaMatch = b, a && (a.browser = window.jQBrowser), window.jQBrowser });
// select2 zh-CN
// eslint-disable-next-line
(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/zh-CN",[],function(){return{errorLoading:function(){return"无法载入结果"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="请删除"+t+"个字符";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="请再输入至少"+t+"个字符";n='输入关键词搜索';return n},loadingMore:function(){return"载入更多结果"},maximumSelected:function(e){var t="最多只能选择"+e.maximum+"";return t},noResults:function(){return"未找到结果"},searching:function(){return"搜索中..."}}}),{define:e.define,require:e.require}})();
// extends jQuery
(function ($) {
$.fn.extend({

View file

@ -53,7 +53,7 @@ class BatchOperator extends RbFormHandler {
}
getQueryData() {
const qd = this.props.listRef.getLastQueryData()
const qd = this.props.listRef.getLastQueryEntry()
if (~~this.state.dataRange === 1) qd._selected = this.props.listRef.getSelectedIds(true).join('|')
return qd
}

View file

@ -40,7 +40,7 @@ class RbList extends React.Component {
this.pageNo = 1
this.pageSize = $storage.get('ListPageSize') || 20
this.advFilter = $storage.get(this.__defaultFilterKey)
this.advFilterId = $storage.get(this.__defaultFilterKey)
}
render() {
@ -68,7 +68,7 @@ class RbList extends React.Component {
const styles = { width: cWidth + 'px' }
const clazz = `unselect ${item.unsort ? '' : 'sortable'} ${idx === 0 && supportFixedColumns ? 'column-fixed column-fixed-2nd' : ''}`
return <th key={'column-' + item.field} style={styles} className={clazz} data-field={item.field}
onClick={item.unsort ? null : this._sortField.bind(this, item.field)}>
onClick={(e) => !item.unsort && this._sortField(item.field, e)}>
<div style={styles}>
<span style={{ width: (cWidth - 8) + 'px' }}>{item.label}</span>
<i className={'zmdi ' + (item.sort || '')} />
@ -147,6 +147,9 @@ class RbList extends React.Component {
containment: '.rb-datatable-body',
axis: 'x',
helper: 'clone',
start: function () {
that.__columnResizing = true
},
stop: function (event, ui) {
const field = $(event.target).parents('th').data('field')
let left = ui.position.left - 0
@ -161,6 +164,7 @@ class RbList extends React.Component {
}
}
that.setState({ fields: fields }, () => $scroller.perfectScrollbar('update'))
setTimeout(() => that.__columnResizing = false, 100)
}
})
@ -184,7 +188,7 @@ class RbList extends React.Component {
pageNo: this.pageNo,
pageSize: this.pageSize,
filter: this.lastFilter,
advFilter: this.advFilter,
advFilter: this.advFilterId,
sort: field_sort,
reload: this.pageNo === 1
}
@ -298,6 +302,7 @@ class RbList extends React.Component {
//
_sortField(field, e) {
if (this.__columnResizing) return // fix: firefox
const fields = this.state.fields
for (let i = 0; i < fields.length; i++) {
if (fields[i].field === field) {
@ -332,7 +337,7 @@ class RbList extends React.Component {
* 设置高级过滤器ID
*/
setAdvFilter(id) {
this.advFilter = id
this.advFilterId = id
this.pageNo = 1
this.fetchList(this.__buildQuick())
if (id) $storage.set(this.__defaultFilterKey, id)
@ -343,15 +348,14 @@ class RbList extends React.Component {
* 搜索
*/
search(filter, fromAdv) {
const afHold = this.advFilter
if (fromAdv === true) this.advFilter = null
//
if (fromAdv === true) this.advFilterId = null
this.pageNo = 1
this.fetchList(filter)
// No keep last filter
if (fromAdv === true) {
this.advFilter = afHold
this.lastFilter = null
$('.J_advfilter .indicator-primary').remove()
if (filter.items.length > 0) $('<i class="indicator-primary"></i>').appendTo('.J_advfilter')
}
}
@ -387,9 +391,9 @@ class RbList extends React.Component {
}
/**
* 获取最后查询过滤数据
* 获取最后查询条件
*/
getLastQueryData() {
getLastQueryEntry() {
return JSON.parse(JSON.stringify(this.__lastQueryEntry)) // Use clone
}

View file

@ -225,48 +225,51 @@ var __checkMessage = function () {
else $('.J_notifications-top .indicator').addClass('hide')
if (__checkMessage__state !== res.data.unread) {
__checkMessage__state = res.data.unread
if (__checkMessage__state > 0) {
if (!window.__doctitle) window.__doctitle = document.title
document.title = '(' + __checkMessage__state + ') ' + window.__doctitle
if (rb.env === 'dev') __showNotification()
}
__loadMessages__state = 0
__loadMessages_state = false
}
__checkMessage__state = res.data.unread
setTimeout(__checkMessage, rb.env === 'dev' ? 60 * 10000 : 2000)
})
}
var __loadMessages__state = 0
var __loadMessages_state = false
var __loadMessages = function () {
if (__loadMessages__state === 1) return
if (__loadMessages_state) return
var dest = $('.rb-notifications .content ul').empty()
if (dest.find('li').length === 0) {
$('<li class="text-center mt-3 mb-3"><i class="zmdi zmdi-refresh zmdi-hc-spin fs-18"></i></li>').appendTo(dest)
}
$.get('/notification/messages?pageSize=10&preview=true', function (res) {
dest.empty()
$(res.data).each(function (idx, item) {
var o = $('<li class="notification"></li>').appendTo(dest)
if (item[3] === true) o.addClass('notification-unread')
o = $('<a class="a" href="' + rb.baseUrl + '/notifications#' + (item[3] ? 'unread' : 'all') + '"></a>').appendTo(o)
o = $('<a class="a" href="' + rb.baseUrl + '/notifications#' + (item[3] ? 'unread=' : 'all=') + item[4] + '"></a>').appendTo(o)
$('<div class="image"><img src="' + rb.baseUrl + '/account/user-avatar/' + item[0][0] + '" alt="Avatar"></div>').appendTo(o)
o = $('<div class="notification-info"></div>').appendTo(o)
$('<div class="text text-truncate">' + item[1] + '</div>').appendTo(o)
$('<span class="date">' + item[2] + '</span>').appendTo(o)
})
__loadMessages__state = 1
__loadMessages_state = true
if (res.data.length === 0) $('<li class="text-center mt-4 mb-4 text-muted">暂无消息</li>').appendTo(dest)
})
}
var __showNotification = function () {
if (window.Notification) {
if (window.Notification.permission === 'granted') {
new Notification('你有 ' + __checkMessage__state + ' 条未读消息', {
tag: 'rbNotification'
var _Notification = window.Notification || window.mozNotification || window.webkitNotification
if (_Notification) {
if (_Notification.permission === 'granted') {
new _Notification('你有 ' + __checkMessage__state + ' 条未读消息', {
tag: 'rbNotification',
icon: rb.baseUrl + '/assets/img/favicon.png',
})
} else {
window.Notification.requestPermission()
_Notification.requestPermission()
}
}
}

View file

@ -23,7 +23,7 @@ class ContentSendNotification extends ActionContentSpec {
<div className="col-12 col-lg-8 pt-1">
<label className="custom-control custom-control-sm custom-radio custom-control-inline mb-1">
<input className="custom-control-input" name="mtype" type="radio" onChange={() => this.setState({ type: 1 })} checked={this.state.type === 1} />
<span className="custom-control-label">内部消息</span>
<span className="custom-control-label">消息通知</span>
</label>
<label className="custom-control custom-control-sm custom-radio custom-control-inline mb-1">
<input className="custom-control-input" name="mtype" type="radio" onChange={() => this.setState({ type: 2 })} checked={this.state.type === 2} />

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -3,7 +3,7 @@
<html>
<head>
<%@ include file="/_include/Head.jsp"%>
<title>待办</title>
<title>待办通知</title>
<style type="text/css">
.notification-info .badge {
border-radius: 99px;
@ -26,7 +26,7 @@
<div class="tab-container">
<ul class="nav nav-tabs nav-tabs-classic notification-tab">
<li class="nav-item">
<a class="nav-link" href="../notifications"><span class="icon zmdi zmdi-notifications"></span> 通知</a>
<a class="nav-link" href="../notifications"><span class="icon zmdi zmdi-notifications"></span> 消息</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="todo"><span class="icon zmdi zmdi-alarm-check"></span> 待办</a>

View file

@ -12,6 +12,8 @@
.vcode-row {
height: 41px;
max-width: 100%;
}
.vcode-row img {
cursor: pointer;
}
.splash-footer *,
@ -79,7 +81,7 @@
<input class="form-control" type="text" placeholder="${bundle.lang('InputCaptcha')}">
</div>
<div class="col-6 text-right pl-0 pr-0">
<img style="max-width:100%;margin-right:-15px" alt="${bundle.lang('Captcha')}" title="${bundle.lang('ClickReload')}">
<img class="mw-100 mr-zero" alt="${bundle.lang('Captcha')}" title="${bundle.lang('ClickReload')}">
</div>
</div>
<div class="form-group row login-tools">

View file

@ -4,6 +4,16 @@
<head>
<%@ include file="/_include/Head.jsp"%>
<title>${bundle.lang('UserSignup')}</title>
<style type="text/css">
.form-group.row {
margin-left: -15px !important;
margin-right: -15px !important;
}
.form-group.row .btn {
height: 41px;
width: 100%;
}
</style>
</head>
<body class="rb-splash-screen">
<div class="rb-wrapper rb-login">
@ -23,12 +33,12 @@
<div class="form-group">
<input class="form-control" id="sEmail" type="email" placeholder="${bundle.lang('Email')}" autocomplete="off">
</div>
<div class="form-group pt-0 row">
<div class="form-group row pt-0">
<div class="col-7">
<input class="form-control" type="text" id="sVcode" placeholder="${bundle.lang('EmailVcode')}" autocomplete="off">
</div>
<div class="col-5 text-right pl-0">
<button class="btn btn-secondary J_vcode-btn" style="height:41px;width:100%" type="button">${bundle.lang('GetVcode')}</button>
<button class="btn btn-primary bordered J_vcode-btn" type="button">${bundle.lang('GetVcode')}</button>
</div>
</div>
<div class="form-group login-submit">

View file

@ -1,19 +1,8 @@
/*
rebuild - Building your business-systems freely.
Copyright (C) 2019 devezhao <zhaofang123@gmail.com>
Copyright (c) REBUILD <https://getrebuild.com/> and its owners. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
rebuild is dual-licensed under commercial and open source licenses (GPLv3).
See LICENSE and COMMERCIAL in the project root for license information.
*/
package com.rebuild.utils;
@ -21,21 +10,54 @@ package com.rebuild.utils;
import org.junit.Test;
/**
* https://www.jianshu.com/p/191d1e21f7ed
*
* @author devezhao-mbp zhaofang123@gmail.com
* @since 2019/05/16
*/
public class MarkdownUtilsTest {
@Test
public void testParse() throws Exception {
String md = "[Click here](/admin/)";
System.out.println(MarkdownUtils.parse(md));
md = "\n"
+ "|COL1|COL2|COL3|"
+ "\n|---|---|---|"
+ "\n|data|data||"
+ "\n[Table 1. caption]";
System.out.println(MarkdownUtils.parse(md));
public void testRender() throws Exception {
render("hello" +
"\n word");
render("# Head");
render("## Head");
render("*A*");
render("**A**");
render("***A***");
render("***");
render("> P");
render("> P" +
">> P" +
"\n>>> P");
render("`CODE`");
render("```" +
"\nCODE" +
"\n```");
render("[Click here](/admin/)");
render("![alt](/img.png)");
render("|COL1|COL2|COL3|"
+ "\n|---|---|---|"
+ "\n|data|data||"
+ "\n[Table 1. caption]");
render("1. a" +
"\n 1. a1" +
"\n2. b");
}
private void render(String md) {
System.out.println("MD: ");
System.out.println(md);
System.out.println("HTML :");
System.out.println(MarkdownUtils.render(md));
}
}