Merge branch 'fix'
This commit is contained in:
@@ -54,7 +54,8 @@ class Admin
|
||||
private Manager $adminNotificationManager,
|
||||
private SystemRequirements $systemRequirements,
|
||||
private ScheduledJob $scheduledJob,
|
||||
private DataManager $dataManager
|
||||
private DataManager $dataManager,
|
||||
private Config\SystemConfig $systemConfig,
|
||||
) {
|
||||
if (!$this->user->isAdmin()) {
|
||||
throw new Forbidden();
|
||||
@@ -179,9 +180,14 @@ class Admin
|
||||
* database: array<string, array<string, mixed>>,
|
||||
* permission: array<string, array<string, mixed>>,
|
||||
* }
|
||||
* @throws Forbidden
|
||||
*/
|
||||
public function getActionSystemRequirementList(): object
|
||||
{
|
||||
if (!$this->user->isSuperAdmin() && $this->systemConfig->isRestrictedMode()) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
return (object) $this->systemRequirements->getAllRequiredList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,4 +50,14 @@ class SystemConfig
|
||||
{
|
||||
return (string) $this->config->get('version');
|
||||
}
|
||||
|
||||
/**
|
||||
* Is restricted mode.
|
||||
*
|
||||
* @since 9.1.8
|
||||
*/
|
||||
public function isRestrictedMode(): bool
|
||||
{
|
||||
return (bool) $this->config->get('restrictedMode');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,6 +232,10 @@ class Email extends Entity
|
||||
return $this->getFromContainer(self::ATTR_BODY_PLAIN);
|
||||
}
|
||||
|
||||
if (!$this->isHtml()) {
|
||||
return $this->getBody();
|
||||
}
|
||||
|
||||
$body = $this->getBody() ?: '';
|
||||
|
||||
return EmailUtil::stripHtml($body) ?: null;
|
||||
|
||||
@@ -2,16 +2,23 @@
|
||||
<span class="breadcrumb-separator"><span></span></span>
|
||||
{{translate 'System Requirements' scope='Admin'}}</h3></div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<table class="table table-striped table-no-overflow table-fixed">
|
||||
<thead>
|
||||
{{#if noAccess}}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
{{translate 'error403' category='messages'}}
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="panel panel-default">
|
||||
<table class="table table-striped table-no-overflow table-fixed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><h5>{{translate 'PHP Settings' scope='Admin'}}</h5></th>
|
||||
<th style="width: 24%"></th>
|
||||
<th style="width: 24%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each phpRequirementList}}
|
||||
<tr class="list-row">
|
||||
<td class="cell">
|
||||
@@ -21,27 +28,27 @@
|
||||
<td class="cell">
|
||||
{{#if acceptable}} <span class="text-success">{{translate 'Success' scope='Admin'}}</span>
|
||||
{{else}}
|
||||
<span class="text-danger">{{translate 'Fail' scope='Admin'}}
|
||||
{{#ifEqual type 'lib'}} ({{translate 'extension is missing' scope='Admin'}}) {{/ifEqual}}
|
||||
{{#ifEqual type 'param'}} ({{required}} {{translate 'is recommended' scope='Admin'}}) {{/ifEqual}}
|
||||
<span class="text-danger">{{translate 'Fail' scope='Admin'}}
|
||||
{{#ifEqual type 'lib'}} ({{translate 'extension is missing' scope='Admin'}}) {{/ifEqual}}
|
||||
{{#ifEqual type 'param'}} ({{required}} {{translate 'is recommended' scope='Admin'}}) {{/ifEqual}}
|
||||
</span> {{/if}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<table class="table table-striped table-no-overflow table-fixed">
|
||||
<thead>
|
||||
<div class="panel panel-default">
|
||||
<table class="table table-striped table-no-overflow table-fixed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><h5>{{translate 'Database Settings' scope='Admin'}}</h5></th>
|
||||
<th style="width: 24%"></th>
|
||||
<th style="width: 24%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each databaseRequirementList}}
|
||||
<tr class="">
|
||||
<td class="cell">
|
||||
@@ -50,29 +57,29 @@
|
||||
<td class="cell" style="width: 24%">{{actual}}</td>
|
||||
<td class="cell" style="width: 24%">
|
||||
{{#if acceptable}}
|
||||
<span class="text-success">{{translate 'Success' scope='Admin'}}</span>
|
||||
<span class="text-success">{{translate 'Success' scope='Admin'}}</span>
|
||||
{{else}}
|
||||
<span class="text-danger">{{translate 'Fail' scope='Admin'}}
|
||||
{{#ifEqual type 'param'}} ({{required}} {{translate 'is recommended' scope='Admin'}}) {{/ifEqual}}
|
||||
<span class="text-danger">{{translate 'Fail' scope='Admin'}}
|
||||
{{#ifEqual type 'param'}} ({{required}} {{translate 'is recommended' scope='Admin'}}) {{/ifEqual}}
|
||||
</span>
|
||||
{{/if}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<table class="table table-striped table-no-overflow table-fixed">
|
||||
<thead>
|
||||
<div class="panel panel-default">
|
||||
<table class="table table-striped table-no-overflow table-fixed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><h5>{{translate 'Permissions' scope='Admin'}}</h5></th>
|
||||
<th style="width: 24%"></th>
|
||||
<th style="width: 24%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each permissionRequirementList}}
|
||||
<tr>
|
||||
<td class="cell">
|
||||
@@ -81,24 +88,25 @@
|
||||
<td class="cell" style="width: 24%">{{translate type scope='Admin' category='systemRequirements'}}</td>
|
||||
<td class="cell" style="width: 24%">
|
||||
{{#if acceptable}}
|
||||
<span class="text-success">{{translate 'Success' scope='Admin'}}</span>
|
||||
<span class="text-success">{{translate 'Success' scope='Admin'}}</span>
|
||||
{{else}}
|
||||
<span class="text-danger">{{translate 'Fail' scope='Admin'}}</span>
|
||||
<span class="text-danger">{{translate 'Fail' scope='Admin'}}</span>
|
||||
{{/if}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="pull-right">
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://docs.espocrm.com/administration/server-configuration/"
|
||||
><strong>{{translate 'Configuration Instructions' scope='Admin'}}</strong></a>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="pull-right">
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://docs.espocrm.com/administration/server-configuration/"
|
||||
><strong>{{translate 'Configuration Instructions' scope='Admin'}}</strong></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
@@ -36,7 +36,6 @@ export default class extends View {
|
||||
targetEntityType = null
|
||||
storageKey = 'formulaSandbox'
|
||||
|
||||
|
||||
setup() {
|
||||
const entityTypeList = [''].concat(
|
||||
this.getMetadata()
|
||||
@@ -132,7 +131,7 @@ export default class extends View {
|
||||
return;
|
||||
}
|
||||
|
||||
let dataToStore = {
|
||||
const dataToStore = {
|
||||
script: this.model.get('script'),
|
||||
targetType: this.model.get('targetType'),
|
||||
targetId: this.model.get('targetId'),
|
||||
@@ -143,6 +142,13 @@ export default class extends View {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {import('views/record/detail').default}
|
||||
*/
|
||||
getRecordView() {
|
||||
return this.getView('record');
|
||||
}
|
||||
|
||||
createRecordView() {
|
||||
return this.createView('record', 'views/admin/formula-sandbox/record/edit', {
|
||||
selector: '.record',
|
||||
@@ -157,7 +163,7 @@ export default class extends View {
|
||||
this.setPageTitle(this.getLanguage().translate('Formula Sandbox', 'labels', 'Admin'));
|
||||
}
|
||||
|
||||
run() {
|
||||
async run() {
|
||||
const script = this.model.get('script');
|
||||
|
||||
this.model.set({
|
||||
@@ -175,50 +181,62 @@ export default class extends View {
|
||||
return;
|
||||
}
|
||||
|
||||
Espo.Ajax
|
||||
.postRequest('Formula/action/run', {
|
||||
this.getRecordView().disableActionItems();
|
||||
Espo.Ui.notifyWait();
|
||||
|
||||
/** @var {Record} */
|
||||
let response;
|
||||
|
||||
try {
|
||||
response = await Espo.Ajax.postRequest('Formula/action/run', {
|
||||
expression: script,
|
||||
targetId: this.model.get('targetId'),
|
||||
targetType: this.model.get('targetType'),
|
||||
})
|
||||
.then(response => {
|
||||
this.model.set('output', response.output || null);
|
||||
|
||||
let errorMessage = null;
|
||||
|
||||
if (!response.isSuccess) {
|
||||
errorMessage = response.message || null;
|
||||
}
|
||||
|
||||
this.model.set('errorMessage', errorMessage);
|
||||
|
||||
if (response.isSuccess) {
|
||||
Espo.Ui.success(
|
||||
this.translate('runSuccess', 'messages', 'Formula')
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.isSyntaxError) {
|
||||
let msg = this.translate('checkSyntaxError', 'messages', 'Formula');
|
||||
|
||||
if (response.message) {
|
||||
msg += ' ' + response.message;
|
||||
}
|
||||
|
||||
Espo.Ui.error(msg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let msg = this.translate('runError', 'messages', 'Formula');
|
||||
|
||||
if (response.message) {
|
||||
msg += ' ' + response.message;
|
||||
}
|
||||
|
||||
Espo.Ui.error(msg);
|
||||
});
|
||||
} catch (e) {
|
||||
this.getRecordView().enableActionItems();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.getRecordView().enableActionItems();
|
||||
|
||||
this.model.set('output', response.output || null);
|
||||
|
||||
let errorMessage = null;
|
||||
|
||||
if (!response.isSuccess) {
|
||||
errorMessage = response.message || null;
|
||||
}
|
||||
|
||||
this.model.set('errorMessage', errorMessage);
|
||||
|
||||
if (response.isSuccess) {
|
||||
Espo.Ui.success(
|
||||
this.translate('runSuccess', 'messages', 'Formula')
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.isSyntaxError) {
|
||||
let msg = this.translate('checkSyntaxError', 'messages', 'Formula');
|
||||
|
||||
if (response.message) {
|
||||
msg += ' ' + response.message;
|
||||
}
|
||||
|
||||
Espo.Ui.error(msg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let msg = this.translate('runError', 'messages', 'Formula');
|
||||
|
||||
if (response.message) {
|
||||
msg += ' ' + response.message;
|
||||
}
|
||||
|
||||
Espo.Ui.error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
************************************************************************/
|
||||
|
||||
import View from 'view';
|
||||
import Ajax from 'ajax';
|
||||
|
||||
export default class extends View {
|
||||
|
||||
@@ -35,25 +36,40 @@ export default class extends View {
|
||||
/** @type {Record} */
|
||||
requirements
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
noAccess = false
|
||||
|
||||
data() {
|
||||
return {
|
||||
phpRequirementList: this.requirements.php,
|
||||
databaseRequirementList: this.requirements.database,
|
||||
permissionRequirementList: this.requirements.permission,
|
||||
noAccess: this.noAccess,
|
||||
};
|
||||
}
|
||||
|
||||
setup() {
|
||||
this.requirements = {};
|
||||
|
||||
this.wait(this.loadData());
|
||||
}
|
||||
|
||||
async loadData() {
|
||||
Espo.Ui.notifyWait();
|
||||
|
||||
const promise = Espo.Ajax.getRequest('Admin/action/systemRequirementList').then(requirements => {
|
||||
this.requirements = requirements;
|
||||
try {
|
||||
this.requirements = await Espo.Ajax.getRequest('Admin/action/systemRequirementList');
|
||||
} catch(e) {
|
||||
this.noAccess = true;
|
||||
|
||||
Espo.Ui.notify();
|
||||
});
|
||||
if ('errorIsHandled' in e) {
|
||||
e.errorIsHandled = true;
|
||||
}
|
||||
}
|
||||
|
||||
this.wait(promise);
|
||||
Espo.Ui.notify();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.filter > .form-group .field .selectize-control,
|
||||
.selectize-control.input-sm {
|
||||
.selectize-control.input-sm.form-control {
|
||||
&.multi {
|
||||
.selectize-input {
|
||||
font-size: var(--font-size-small);
|
||||
|
||||
@@ -495,6 +495,7 @@ class EmailTest extends TestCase
|
||||
public function testBodyPlain(): void
|
||||
{
|
||||
$this->email->setBody('<br /> &');
|
||||
$this->email->setIsHtml();
|
||||
$bodyPlain = $this->email->getBodyPlain();
|
||||
|
||||
$this->assertEquals(" \r\n &", $bodyPlain);
|
||||
|
||||
Reference in New Issue
Block a user