PMCORE-2352 User extended attributes PMCORE-2247

This commit is contained in:
Roly Rudy Gutierrez Pinto
2020-12-16 19:47:59 -04:00
parent 9311905f74
commit d57a3ac932
65 changed files with 39216 additions and 153 deletions

View File

@@ -3,7 +3,15 @@
global $G_PUBLISH;
$G_PUBLISH = new Publisher();
try {
echo file_get_contents(PATH_HOME . "public_html/lib/authenticationSources/index.html");
$conf = new Configurations();
$pageSize = $conf->getEnvSetting('casesListRowNumber');
$pageSize = empty($pageSize) ? 25 : $pageSize;
$lang = defined("SYS_LANG") ? SYS_LANG : "en";
$html = file_get_contents(PATH_HTML . "lib/authenticationSources/index.html");
$html = str_replace("var pageSize=10;", "var pageSize={$pageSize};", $html);
$html = str_replace("translation.en.js", "translation.{$lang}.js", $html);
echo $html;
} catch (Exception $e) {
$message = [
'MESSAGE' => $e->getMessage()

View File

@@ -6,7 +6,11 @@
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<!-- These are default values, then they are overridden when processmaker runs -->
<script type="text/javascript" src="/js/ext/translation.en.js"></script>
<script type="text/javascript">
var pageSize=10;
</script>
</head>
<body>
<noscript>

View File

@@ -102,7 +102,7 @@
saveNewConnection(form) {
let formData = this.$refs.newConnection.formToFormData(form);
axios.post(this.$root.baseUrl() + "ldapAdvancedProxy.php?functionAccion=ldapSave", formData)
axios.post(this.$root.baseUrl() + "authSources/ldapAdvancedProxy.php?functionAccion=ldapSave", formData)
.then(response => {
response;
this.$refs.authenticationSources.refresh();

View File

@@ -97,7 +97,7 @@
},
data() {
return {
baseUrl: this.$root.baseUrl() + "/authSources_Ajax?action=authSourcesList",
baseUrl: this.$root.baseUrl() + "authSources/authSources_Ajax?action=authSourcesList",
columns: [
"AUTH_SOURCE_NAME",
"AUTH_SOURCE_PROVIDER",
@@ -140,7 +140,7 @@
noResults: this.$root.translation("ID_NO_MATCHING_RECORDS"),
loading: this.$root.translation("ID_LOADING_GRID")
},
perPage: 5,
perPage: "pageSize" in window ? window.pageSize : 5,
perPageValues: [],
sortIcon: {
is: "glyphicon-sort",
@@ -194,7 +194,7 @@
let formData = new FormData();
formData.append("action", "deleteAuthSource");
formData.append("auth_uid", row.AUTH_SOURCE_UID);
axios.post(this.$root.baseUrl() + "authSources_Ajax", formData)
axios.post(this.$root.baseUrl() + "authSources/authSources_Ajax", formData)
.then(response => {
response;
this.refresh();
@@ -253,11 +253,11 @@
},
syncGroups(row) {
//the return action is in: processmaker/workflow/engine/templates/authSources/authSourcesSynchronize.js
location.href = this.$root.baseUrl() + "authSourcesSynchronize?authUid=" + row.AUTH_SOURCE_UID + "&tab=synchronizeGroups";
location.href = this.$root.baseUrl() + "authSources/authSourcesSynchronize?authUid=" + row.AUTH_SOURCE_UID + "&tab=synchronizeGroups";
},
syncDepartments(row) {
//the return action is in: processmaker/workflow/engine/templates/authSources/authSourcesSynchronize.js
location.href = this.$root.baseUrl() + "authSourcesSynchronize?authUid=" + row.AUTH_SOURCE_UID + "&tab=synchronizeDepartments";
location.href = this.$root.baseUrl() + "authSources/authSourcesSynchronize?authUid=" + row.AUTH_SOURCE_UID + "&tab=synchronizeDepartments";
},
optionSaveButton(fileContent) {
this.$refs['as-b-modal-upload-file'].hide();

View File

@@ -11,7 +11,7 @@
<b-form-group :label="$root.translation('ID_NAME')">
<b-form-input v-model="form.name"
:state="validateState('name')"
placeholder=""/>
autocomplete="off"/>
<b-form-invalid-feedback>{{$root.translation('ID_IS_REQUIRED')}}</b-form-invalid-feedback>
</b-form-group>
<b-form-group :label="$root.translation('ID_TYPE')">
@@ -28,13 +28,13 @@
<b-form-group :label="$root.translation('ID_SERVER_ADDRESS')">
<b-form-input v-model="form.serverAddress"
:state="validateState('serverAddress')"
placeholder=""/>
autocomplete="off"/>
<b-form-invalid-feedback>{{$root.translation('ID_IS_REQUIRED')}}</b-form-invalid-feedback>
</b-form-group>
<b-form-group :label="$root.translation('ID_PORT')">
<b-form-input v-model="form.port"
:state="validateState('port')"
placeholder=""/>
autocomplete="off"/>
<b-form-invalid-feedback>{{$root.translation('ID_IS_REQUIRED')}}</b-form-invalid-feedback>
</b-form-group>
<b-form-group :label="$root.translation('ID_ENABLE_AUTOMATIC_REGISTER')"
@@ -60,11 +60,12 @@
</b-form-group>
<b-form-group :label="$root.translation('ID_BASE_DN')">
<b-form-input v-model="form.baseDN"
placeholder="dc=business,dc=net"/>
placeholder="dc=business,dc=net"
autocomplete="off"/>
</b-form-group>
<b-form-group :label="$root.translation('ID_INACTIVE_USERS')">
<b-form-input v-model="form.inactiveUsers"
placeholder=""/>
autocomplete="off"/>
</b-form-group>
<b-form-group :label="$root.translation('ID_ROLE')">
<b-form-select v-model="form.role"
@@ -81,40 +82,41 @@
<b-form-group :label="$root.translation('ID_USERNAME')">
<b-form-input v-model="form.userName"
:state="validateState('userName')"
placeholder=""/>
autocomplete="off"/>
<b-form-invalid-feedback>{{$root.translation('ID_IS_REQUIRED')}}</b-form-invalid-feedback>
</b-form-group>
<b-form-group :label="$root.translation('ID_PASSWORD')">
<b-form-input v-model="form.password"
:state="validateState('password')"
type="password"/>
type="password"
autocomplete="off"/>
<b-form-invalid-feedback>{{$root.translation('ID_IS_REQUIRED')}}</b-form-invalid-feedback>
</b-form-group>
<b-form-group :label="$root.translation('ID_USER_IDENTIFIER')">
<b-form-input v-model="form.userIdentifier"
placeholder=""
autocomplete="off"
readonly/>
</b-form-group>
<b-form-group :label="$root.translation('ID_GROUP_IDENTIFIER')">
<b-form-input v-model="form.groupIdentifier"
placeholder=""
autocomplete="off"
readonly/>
</b-form-group>
<b-form-group :label="$root.translation('ID_FILTER_TO_SEARCH_USERS')">
<b-form-input v-model="form.filterToSearchUsers"
placeholder=""/>
autocomplete="off"/>
</b-form-group>
<b-form-group :label="$root.translation('ID_USER_CLASS_IDENTIFIER')">
<b-form-input v-model="form.userClassIdentifier"
placeholder=""/>
autocomplete="off"/>
</b-form-group>
<b-form-group :label="$root.translation('ID_GROUP_CLASS_IDENTIFIER')">
<b-form-input v-model="form.groupClassIdentifier"
placeholder=""/>
autocomplete="off"/>
</b-form-group>
<b-form-group :label="$root.translation('ID_DEPARTMENT_CLASS_IDENTIFIER')">
<b-form-input v-model="form.departmentClassIdentifier"
placeholder=""/>
autocomplete="off"/>
</b-form-group>
</b-col>
</b-row>
@@ -270,12 +272,12 @@
test(form) {
let formDataForName = new FormData();
formDataForName.append("AUTH_SOURCE_NAME", form.name);
axios.post(this.$root.baseUrl() + "ldapAdvancedProxy.php?functionAccion=ldapVerifyName", formDataForName)
axios.post(this.$root.baseUrl() + "authSources/ldapAdvancedProxy.php?functionAccion=ldapVerifyName", formDataForName)
.then(response => {
//the name is valid
if (response.data.row === false || (this.form.uid !== "" && typeof this.form.uid === "string")) {
let formData = this.formToFormData(form);
axios.post(this.$root.baseUrl() + "ldapAdvancedProxy.php?functionAccion=ldapTestConnection", formData)
axios.post(this.$root.baseUrl() + "authSources/ldapAdvancedProxy.php?functionAccion=ldapTestConnection", formData)
.then(response => {
//test is successful
if (response.data.status === "OK") {

View File

@@ -141,7 +141,7 @@
//validation name
let formData = new FormData();
formData.append("AUTH_SOURCE_NAME", this.fileContent.AUTH_SOURCE_NAME);
axios.post(this.$root.baseUrl() + "ldapAdvancedProxy.php?functionAccion=ldapVerifyName", formData)
axios.post(this.$root.baseUrl() + "authSources/ldapAdvancedProxy.php?functionAccion=ldapVerifyName", formData)
.then(response => {
this.newName = response.data.row === false;
this.validationResult = response.data;

View File

@@ -12,32 +12,20 @@
:data="rows">
<div slot="icons"
slot-scope="props">
<b-button :id="'ma-b-button-tooltip-'+props.index"
variant="light"
size="sm"
class="mb-2">
<b-icon icon="three-dots-vertical" aria-hidden="true"/>
</b-button>
<b-tooltip :target="'ma-b-button-tooltip-'+props.index"
triggers="hover focus click"
custom-class="custom-tooltip"
placement="left"
variant="light">
<b-button-group>
<b-button @click="editAttribute(props.row,props.index)"
v-b-tooltip.hover
:title="$root.translation('ID_EDIT_ATTRIBUTE')"
variant="light">
<b-icon icon="pencil-fill" aria-hidden="true" variant="info"/>
</b-button>
<b-button @click="deleteAttribute(props.index,props.row)"
v-b-tooltip.hover
:title="$root.translation('ID_DELETE_ATTRIBUTE')"
variant="light">
<b-icon icon="trash" aria-hidden="true" variant="danger"/>
</b-button>
</b-button-group>
</b-tooltip>
<b-button-group>
<b-button @click="editAttribute(props.row,props.index)"
v-b-tooltip.hover
:title="$root.translation('ID_EDIT_ATTRIBUTE')"
variant="light">
<b-icon icon="pencil-fill" aria-hidden="true" variant="info"/>
</b-button>
<b-button @click="deleteAttribute(props.index,props.row)"
v-b-tooltip.hover
:title="$root.translation('ID_DELETE_ATTRIBUTE')"
variant="light">
<b-icon icon="trash" aria-hidden="true" variant="danger"/>
</b-button>
</b-button-group>
</div>
</v-client-table>
<b-modal id="messageForDeleteAttribute"

View File

@@ -7,7 +7,8 @@
<b-col>
<b-form-group :label="$root.translation('ID_ROLE')">
<b-form-select v-model="form.attributeRole"
:options="roles"/>
:options="roles"
@change="changeRoles"/>
</b-form-group>
<b-form-group :label="$root.translation('ID_PROCESSMAKER_USER_FIELD')" description="">
<b-form-select v-model="form.attributeUser"
@@ -15,8 +16,8 @@
</b-form-group>
<b-form-group :label="$root.translation('ID_LDAP_ATTRIBUTE')">
<b-form-input v-model="form.attributeLdap"
:state="validateState('attributeLdap')"
placeholder=""/>
:state="true"
autocomplete="off"/>
<b-form-invalid-feedback>{{$root.translation('ID_IS_REQUIRED')}}</b-form-invalid-feedback>
</b-form-group>
</b-col>
@@ -35,6 +36,7 @@
</template>
<script>
import axios from "axios"
import { validationMixin } from "vuelidate"
import { required } from "vuelidate/lib/validators"
import titleSection from "./titleSection.vue"
@@ -56,38 +58,20 @@
index: null,
attributeLdap: "",
attributeRole: "",
attributeUser: "USR_FIRSTNAME"
attributeUser: ""
},
roles: [
{value: "", text: "All"},
{value: "PROCESSMAKER_ADMIN", text: this.$root.translation("ID_SYSTEM_ADMINISTRATOR")},
{value: "PROCESSMAKER_MANAGER", text: this.$root.translation("ID_MANAGER")},
{value: "PROCESSMAKER_OPERATOR", text: this.$root.translation("ID_OPERATOR")}
],
userAttributes: [
{value: "USR_FIRSTNAME", text: "USR_FIRSTNAME"},
{value: "USR_LASTNAME", text: "USR_LASTNAME"},
{value: "USR_EMAIL", text: "USR_EMAIL"},
{value: "USR_DUE_DATE", text: "USR_DUE_DATE"},
{value: "USR_STATUS", text: "USR_STATUS"},
{value: "USR_STATUS_ID", text: "USR_STATUS_ID"},
{value: "USR_ADDRESS", text: "USR_ADDRESS"},
{value: "USR_PHONE", text: "USR_PHONE"},
{value: "USR_FAX", text: "USR_FAX"},
{value: "USR_CELLULAR", text: "USR_CELLULAR"},
{value: "USR_ZIP_CODE", text: "USR_ZIP_CODE"},
{value: "USR_POSITION", text: "USR_POSITION"},
{value: "USR_BIRTHDAY", text: "USR_BIRTHDAY"},
{value: "USR_COST_BY_HOUR", text: "USR_COST_BY_HOUR"},
{value: "USR_UNIT_COST", text: "USR_UNIT_COST"},
{value: "USR_PMDRIVE_FOLDER_UID", text: "USR_PMDRIVE_FOLDER_UID"},
{value: "USR_BOOKMARK_START_CASES", text: "USR_BOOKMARK_START_CASES"},
{value: "USR_TIME_ZONE", text: "USR_TIME_ZONE"},
{value: "USR_DEFAULT_LANG", text: "USR_DEFAULT_LANG"},
{value: "USR_LAST_LOGIN", text: "USR_LAST_LOGIN"}
]
roles: [{
value: "", text: "All"
}],
userAttributes: []
};
},
mounted() {
let promise = this.getRolesList();
promise.then(response => {
this.changeRoles();
});
},
methods: {
validateState(name) {
const {$dirty, $error} = this.$v.form[name];
@@ -111,8 +95,58 @@
index: null,
attributeLdap: "",
attributeRole: "",
attributeUser: "USR_FIRSTNAME"
attributeUser: ""
};
},
changeRoles() {
let formData = new FormData();
formData.append("option", "listByRol");
formData.append("rolCode", this.form.attributeRole);
return axios.post(this.$root.baseUrl() + "userExtendedAttributes/index", formData)
.then(response => {
response;
let data = [{
value: "",
text: this.$root.translation('ID_SELECTED_FIELD')
}];
for (let i in response.data.data) {
data.push({
value: response.data.data[i].value,
text: response.data.data[i].text
});
}
this.userAttributes = data;
})
.catch(error => {
error;
})
.finally(() => {
});
},
getRolesList() {
let formData = new FormData();
formData.append("request", "allRoles");
return axios.post(this.$root.baseUrl() + "roles/roles_Ajax", formData)
.then(response => {
response;
let data = [{
value: "",
text: this.$root.translation('ID_ALL')
}];
for (let i in response.data) {
data.push({
value: response.data[i].ROL_CODE,
text: response.data[i].ROL_NAME
});
}
this.roles = data;
})
.catch(error => {
error;
})
.finally(() => {
});
}
}
}

View File

@@ -27,7 +27,7 @@ new Vue({
return text;
},
baseUrl() {
return "../authSources/";
return "../";
}
}
}).$mount('#app');

View File

@@ -1,26 +1,7 @@
<?php
/**
* upgrade.php
*
* ProcessMaker Open Source Edition
* Copyright (C) 2004 - 2008 Colosa Inc.23
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* For more information, contact Colosa Inc, 2566 Le Jeune Rd.,
* Coral Gables, FL, 33134, USA, or email info@colosa.com.
*/
use Illuminate\Support\Facades\DB;
use ProcessMaker\BusinessModel\Role;
use ProcessMaker\Exception\RBACException;
global $RBAC;
@@ -250,46 +231,54 @@ switch ($REQUEST) {
}
break;
case 'rolesList':
$co = new Configurations();
$config = $co->getConfiguration( 'rolesList', 'pageSize', '', $_SESSION['USER_LOGGED'] );
$limit_size = isset( $config['pageSize'] ) ? $config['pageSize'] : 20;
$configurations = new Configurations();
$config = $configurations->getConfiguration('rolesList', 'pageSize', '', $_SESSION['USER_LOGGED']);
$limitSize = isset($config['pageSize']) ? $config['pageSize'] : 20;
$start = isset( $_POST['start'] ) ? $_POST['start'] : 0;
$limit = isset( $_POST['limit'] ) ? $_POST['limit'] : $limit_size;
$filter = isset( $_REQUEST['textFilter'] ) ? $_REQUEST['textFilter'] : '';
$start = isset($_POST['start']) ? $_POST['start'] : 0;
$limit = isset($_POST['limit']) ? $_POST['limit'] : $limitSize;
$filter = isset($_REQUEST['textFilter']) ? $_REQUEST['textFilter'] : '';
global $RBAC;
$Criterias = $RBAC->getAllRolesFilter( $start, $limit, $filter );
$criterias = $RBAC->getAllRolesFilter($start, $limit, $filter);
$rs = RolesPeer::DoSelectRs( $Criterias['LIST'] );
$rs->setFetchmode( ResultSet::FETCHMODE_ASSOC );
$rs = RolesPeer::DoSelectRs($criterias['LIST']);
$rs->setFetchmode(ResultSet::FETCHMODE_ASSOC);
$content = new Content();
$rNames = $content->getAllContentsByRole();
$aUsers = $RBAC->getAllUsersByRole();
$aRows = Array ();
$names = $content->getAllContentsByRole();
$users = $RBAC->getAllUsersByRole();
$rows = Array();
while ($rs->next()) {
$aRows[] = $rs->getRow();
$index = sizeof( $aRows ) - 1;
$roleUid = $aRows[$index]['ROL_UID'];
if (!isset($rNames[$roleUid])) {
$rows[] = $rs->getRow();
$index = sizeof($rows) - 1;
$roleUid = $rows[$index]['ROL_UID'];
if (!isset($names[$roleUid])) {
$rol = new Roles();
$row = $rol->load($roleUid);
$rolname = $row['ROL_NAME'];
$rolName = $row['ROL_NAME'];
} else {
$rolname = $rNames[$roleUid];
$rolName = $names[$roleUid];
}
$aRows[$index]['ROL_NAME'] = $rolname;
$aRows[$index]['TOTAL_USERS'] = isset( $aUsers[$roleUid] ) ? $aUsers[$roleUid] : 0;
$rows[$index]['ROL_NAME'] = $rolName;
$rows[$index]['TOTAL_USERS'] = isset($users[$roleUid]) ? $users[$roleUid] : 0;
}
$oData = RolesPeer::doSelectRS( $Criterias['COUNTER'] );
$oData->setFetchmode( ResultSet::FETCHMODE_ASSOC );
$oData->next();
$row = $oData->getRow();
$total_roles = $row['CNT'];
$data = RolesPeer::doSelectRS($criterias['COUNTER']);
$data->setFetchmode(ResultSet::FETCHMODE_ASSOC);
$data->next();
$row = $data->getRow();
$totalRoles = $row['CNT'];
echo '{roles: ' . G::json_encode( $aRows ) . ', total_roles: ' . $total_roles . '}';
$result = [
'roles' => $rows,
'total_roles' => $totalRoles
];
echo G::json_encode($result);
break;
case 'allRoles':
$roles = Role::getAllRoles();
echo G::json_encode($roles);
break;
case 'updatePageSize':
$c = new Configurations();

View File

@@ -0,0 +1,24 @@
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
/nbproject/private/

View File

@@ -0,0 +1,24 @@
# my-app
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).

View File

@@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

View File

@@ -0,0 +1,233 @@
<?php
use Illuminate\Support\Facades\DB;
use ProcessMaker\BusinessModel\Role;
use ProcessMaker\Model\UserExtendedAttributes;
global $G_PUBLISH;
$G_PUBLISH = new Publisher();
try {
$option = empty($_REQUEST["option"]) ? '' : $_REQUEST["option"];
switch ($option) {
case "list":
$rbacRoles = Role::getAllRoles();
$orders = [
"attributeName" => "UEA_NAME",
"attribute" => "UEA_ATTRIBUTE_ID",
"role" => "UEA_ROLES",
"dateCreated" => "UEA_DATE_CREATE"
];
$query = empty($_REQUEST["query"]) ? "" : $_REQUEST["query"];
$limit = empty($_REQUEST["limit"]) ? 10 : $_REQUEST["limit"];
$start = empty($_REQUEST["start"]) ? 0 : $_REQUEST["start"];
$ascending = !isset($_REQUEST["ascending"]) ? "1" : $_REQUEST["ascending"];
$orderBy = $orders["attributeName"];
if (!empty($_REQUEST["orderBy"]) && !empty($orders[$_REQUEST["orderBy"]])) {
$orderBy = $orders[$_REQUEST["orderBy"]];
}
$count = UserExtendedAttributes::join('USERS', 'USERS.USR_ID', '=', 'USER_EXTENDED_ATTRIBUTES.UEA_OWNER')
->count();
$userExtendedAttributes = UserExtendedAttributes::query()
->join('USERS', 'USERS.USR_ID', '=', 'USER_EXTENDED_ATTRIBUTES.UEA_OWNER')
->where('UEA_NAME', 'LIKE', "%{$query}%")
->orWhere('UEA_ATTRIBUTE_ID', 'LIKE', "%{$query}%")
->orWhere('UEA_ROLES', 'LIKE', "%{$query}%")
->orWhere('UEA_DATE_CREATE', 'LIKE', "%{$query}%")
->orderBy($orderBy, $ascending === "1" ? "asc" : "desc")
->offset($start)
->limit($limit)
->get()
->toArray();
//change key names
array_walk($userExtendedAttributes, function (&$row) use($rbacRoles) {
foreach ($row as $key => $value) {
$string = $key;
$string = strtolower($string);
$string = str_replace(["uea_"], "", $string);
$string = str_replace("_", " ", $string);
$string = ucwords($string);
$string = lcfirst($string);
$string = str_replace(" ", "", $string);
$row[$string] = $row[$key];
unset($row[$key]);
}
//format owner
$row["owner"] = $row["usrUsername"];
//format roles
$rolesLabel = [];
if (is_array($rbacRoles)) {
$roles = G::json_decode($row["roles"]);
foreach ($roles as $rol) {
foreach ($rbacRoles as $item) {
if (isset($item->ROL_CODE) && $rol === $item->ROL_CODE) {
$rolesLabel[] = $item->ROL_NAME;
}
}
}
}
$row["rolesLabel"] = $rolesLabel;
});
$result = [
"data" => $userExtendedAttributes,
"count" => $count
];
echo G::json_encode($result);
break;
case "userExtendedAttributesList":
$userExtendedAttributes = UserExtendedAttributes::query()
->orderBy('UEA_NAME')
->get()
->toArray();
//change key names
array_walk($userExtendedAttributes, function (&$row) {
foreach ($row as $key => $value) {
$string = $key;
$string = strtolower($string);
$string = str_replace(["uea_"], "", $string);
$string = str_replace("_", " ", $string);
$string = ucwords($string);
$string = lcfirst($string);
$string = str_replace(" ", "", $string);
$row[$string] = $row[$key];
unset($row[$key]);
}
});
$result = [
"data" => $userExtendedAttributes
];
echo json_encode($result);
break;
case "listByRol":
$rolCode = empty($_REQUEST["rolCode"]) ? "" : $_REQUEST["rolCode"];
$userExtendedAttributes = UserExtendedAttributes::query()
->Where("UEA_ROLES", 'LIKE', "%{$rolCode}%")
->orderBy("UEA_NAME", "asc")
->get()
->toArray();
$default = [
["value" => "USR_FIRSTNAME", "text" => "USR_FIRSTNAME", "extended" => false],
["value" => "USR_LASTNAME", "text" => "USR_LASTNAME", "extended" => false],
["value" => "USR_EMAIL", "text" => "USR_EMAIL", "extended" => false],
["value" => "USR_DUE_DATE", "text" => "USR_DUE_DATE", "extended" => false],
["value" => "USR_STATUS", "text" => "USR_STATUS", "extended" => false],
["value" => "USR_STATUS_ID", "text" => "USR_STATUS_ID", "extended" => false],
["value" => "USR_ADDRESS", "text" => "USR_ADDRESS", "extended" => false],
["value" => "USR_PHONE", "text" => "USR_PHONE", "extended" => false],
["value" => "USR_FAX", "text" => "USR_FAX", "extended" => false],
["value" => "USR_CELLULAR", "text" => "USR_CELLULAR", "extended" => false],
["value" => "USR_ZIP_CODE", "text" => "USR_ZIP_CODE", "extended" => false],
["value" => "USR_POSITION", "text" => "USR_POSITION", "extended" => false],
["value" => "USR_BIRTHDAY", "text" => "USR_BIRTHDAY", "extended" => false],
["value" => "USR_COST_BY_HOUR", "text" => "USR_COST_BY_HOUR", "extended" => false],
["value" => "USR_UNIT_COST", "text" => "USR_UNIT_COST", "extended" => false],
["value" => "USR_PMDRIVE_FOLDER_UID", "text" => "USR_PMDRIVE_FOLDER_UID", "extended" => false],
["value" => "USR_BOOKMARK_START_CASES", "text" => "USR_BOOKMARK_START_CASES", "extended" => false],
["value" => "USR_TIME_ZONE", "text" => "USR_TIME_ZONE", "extended" => false],
["value" => "USR_DEFAULT_LANG", "text" => "USR_DEFAULT_LANG", "extended" => false],
["value" => "USR_LAST_LOGIN", "text" => "USR_LAST_LOGIN", "extended" => false]
];
$data = [];
foreach ($userExtendedAttributes as $key => $value) {
$data[] = [
"value" => $value["UEA_ATTRIBUTE_ID"],
"text" => $value["UEA_NAME"],
"extended" => true
];
}
$data = array_merge($data, $default);
$result = [
"data" => $data
];
echo G::json_encode($result);
break;
case "save":
$userUid = empty($_SESSION['USER_LOGGED']) ? RBAC::ADMIN_USER_UID : $_SESSION['USER_LOGGED'];
$user = new Users();
$user = $user->load($userUid);
$userId = empty($user['USR_ID']) ? null : $user['USR_ID'];
$id = empty($_REQUEST["UEA_ID"]) ? "" : $_REQUEST["UEA_ID"];
$name = empty($_REQUEST["UEA_NAME"]) ? "" : $_REQUEST["UEA_NAME"];
$attributeId = empty($_REQUEST["UEA_ATTRIBUTE_ID"]) ? "" : $_REQUEST["UEA_ATTRIBUTE_ID"];
$hidden = empty($_REQUEST["UEA_HIDDEN"]) ? "" : $_REQUEST["UEA_HIDDEN"];
$required = empty($_REQUEST["UEA_REQUIRED"]) ? "" : $_REQUEST["UEA_REQUIRED"];
$password = empty($_REQUEST["UEA_PASSWORD"]) ? "" : $_REQUEST["UEA_PASSWORD"];
$option = empty($_REQUEST["UEA_OPTION"]) ? "" : $_REQUEST["UEA_OPTION"];
$roles = empty($_REQUEST["UEA_ROLES"]) ? "" : $_REQUEST["UEA_ROLES"];
$owner = empty($_REQUEST["UEA_OWNER"]) ? $userId : $_REQUEST["UEA_OWNER"];
$dateCreate = empty($_REQUEST["UEA_DATE_CREATE"]) ? date("Y-m-d H:i:s") : $_REQUEST["UEA_DATE_CREATE"];
$userExtendedAttributes = UserExtendedAttributes::where('UEA_ID', '=', $id)
->get()
->first();
if (empty($userExtendedAttributes)) {
$userExtendedAttributes = new UserExtendedAttributes();
}
$userExtendedAttributes->UEA_NAME = trim($name);
$userExtendedAttributes->UEA_ATTRIBUTE_ID = trim($attributeId);
$userExtendedAttributes->UEA_HIDDEN = $hidden;
$userExtendedAttributes->UEA_REQUIRED = $required;
$userExtendedAttributes->UEA_PASSWORD = $password;
$userExtendedAttributes->UEA_OPTION = $option;
$userExtendedAttributes->UEA_ROLES = $roles;
$userExtendedAttributes->UEA_OWNER = $owner;
$userExtendedAttributes->UEA_DATE_CREATE = $dateCreate;
$userExtendedAttributes->save();
echo G::json_encode($userExtendedAttributes);
break;
case "delete":
$id = empty($_REQUEST["id"]) ? "" : $_REQUEST["id"];
if (!empty($id)) {
$id = UserExtendedAttributes::where('UEA_ID', '=', $id)
->delete();
}
echo G::json_encode($id);
break;
case "verifyName":
$id = empty($_REQUEST["id"]) ? "" : $_REQUEST["id"];
$name = empty($_REQUEST["name"]) ? "" : $_REQUEST["name"];
$userExtendedAttributes = UserExtendedAttributes::query()
->where('UEA_NAME', '=', trim($name))
->where('UEA_ID', '<>', $id)
->get()
->first();
$result = [
"valid" => empty($userExtendedAttributes),
"message" => empty($userExtendedAttributes) ? "" : G::loadTranslation("ID_NAME_EXISTS")
];
echo G::json_encode($result);
break;
case "verifyAttributeId":
$id = empty($_REQUEST["id"]) ? "" : $_REQUEST["id"];
$attributeId = empty($_REQUEST["attributeId"]) ? "" : $_REQUEST["attributeId"];
$userExtendedAttributes = UserExtendedAttributes::query()
->where('UEA_ATTRIBUTE_ID', '=', trim($attributeId))
->where('UEA_ID', '<>', $id)
->get()
->first();
$result = [
"valid" => empty($userExtendedAttributes),
"message" => empty($userExtendedAttributes) ? "" : G::loadTranslation("ID_EXIST")
];
echo G::json_encode($result);
break;
default:
$conf = new Configurations();
$pageSize = $conf->getEnvSetting('casesListRowNumber');
$pageSize = empty($pageSize) ? 25 : $pageSize;
$lang = defined("SYS_LANG") ? SYS_LANG : "en";
$html = file_get_contents(PATH_HTML . "lib/userExtendedAttributes/index.html");
$html = str_replace("var pageSize=10;", "var pageSize={$pageSize};", $html);
$html = str_replace("translation.en.js", "translation.{$lang}.js", $html);
echo $html;
break;
}
} catch (Exception $e) {
$message = [
'MESSAGE' => $e->getMessage()
];
$G_PUBLISH->AddContent('xmlform', 'xmlform', 'login/showMessage', '', $message);
G::RenderPage('publish', 'blank');
}

View File

@@ -0,0 +1,4 @@
file.reference.userExtendedAttributes-public=public
files.encoding=UTF-8
site.root.folder=${file.reference.userExtendedAttributes-public}
source.folder=

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.web.clientproject</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/clientside-project/1">
<name>userExtendedAttributes</name>
</data>
</configuration>
</project>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,51 @@
{
"name": "userExtendedAttributes",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build --dest ../../../public_html/lib/userExtendedAttributes",
"lint": "vue-cli-service lint"
},
"dependencies": {
"@panter/vue-i18next": "^0.15.2",
"@vue/cli": "^4.4.6",
"axios": "^0.19.2",
"bootstrap": "^4.5.0",
"bootstrap-vue": "^2.20.1",
"core-js": "^3.8.1",
"lodash": "^4.17.19",
"save": "^2.4.0",
"vue": "^2.6.11",
"vue-tables-2": "^2.1.61",
"vuelidate": "^0.7.5"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^4.5.9",
"@vue/cli-plugin-eslint": "^4.5.9",
"@vue/cli-service": "^4.5.9",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"vue-template-compiler": "^2.6.11"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<!-- These are default values, then they are overridden when processmaker runs -->
<script type="text/javascript" src="/js/ext/translation.en.js"></script>
<script type="text/javascript">
var pageSize=10;
</script>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@@ -0,0 +1,67 @@
<template>
<div id="app">
<userExtendedAttributes ref="userExtendedAttributes"
v-show="views.userExtendedAttributes"
@newAttribute="newAttribute"
@editAttribute="editAttribute">
</userExtendedAttributes>
<newUserAttribute ref="newUserAttribute"
v-show="views.newUserAttribute"
@save="saveAttribute"
@cancel="cancel">
</newUserAttribute>
</div>
</template>
<script>
import userExtendedAttributes from './components/userExtendedAttributes.vue'
import newUserAttribute from './components/newUserAttribute.vue'
export default {
name: 'app',
components: {
userExtendedAttributes,
newUserAttribute
},
data() {
return {
views: {
userExtendedAttributes: true,
newUserAttribute: false
}
};
},
methods: {
showView(name) {
for (let view in this.views) {
this.views[view] = false;
}
this.views[name] = true;
},
cancel() {
this.showView("userExtendedAttributes");
},
newAttribute() {
this.$refs.newUserAttribute.reset();
this.showView("newUserAttribute");
},
saveAttribute() {
this.showView("userExtendedAttributes");
this.$refs.userExtendedAttributes.refresh();
},
editAttribute(row) {
this.$refs.newUserAttribute.reset();
this.$refs.newUserAttribute.load(row);
this.showView("newUserAttribute");
}
}
}
</script>
<style>
#app {
margin: 20px;
}
.custom-tooltip > .tooltip-inner{
max-width: none;
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@@ -0,0 +1,378 @@
<template>
<div>
<titleSection :title="$root.translation('ID_NEW_USER_ATTRIBUTE')"></titleSection>
<b-form @submit.stop.prevent="onsubmit">
<b-container fluid>
<b-row>
<b-col cols="6">
<b-form-group :label="$root.translation('ID_NAME')">
<b-form-input v-model="form.name"
autocomplete="off"
:state="statusName"
@keyup="validateName"/>
<b-form-invalid-feedback>{{statusNameMessage}}</b-form-invalid-feedback>
</b-form-group>
</b-col>
<b-col>
<b-form-group :label="$root.translation('ID_ATTRIBUTE_ID')">
<b-form-input v-model="form.attributeId"
autocomplete="off"
:state="statusAttributeId"
@keyup="validateAttributeId"/>
<b-form-invalid-feedback>{{statusAttributeIdMessage}}</b-form-invalid-feedback>
</b-form-group>
</b-col>
</b-row>
<b-row>
<b-col cols="6">
<b-form-group :label="$root.translation('ID_PROPERTIES')">
<b-form-checkbox v-model="form.hidden"
value="1"
unchecked-value="0"
:disabled="form.required===1 || form.password===1">
{{$root.translation('ID_HIDDEN')}}
<b-button variant="outline-light"
v-b-tooltip="{title:$root.translation('ID_ATTRIBUTE_WONT_BE_SEEN_IN_USER_INFORMATION'),placement:'right',variant:'warning',customClass:'custom-tooltip'}">
<b-icon icon="question-circle-fill"
aria-hidden="true"
variant="primary"/>
</b-button>
</b-form-checkbox>
<b-form-checkbox v-model="form.required"
value="1"
unchecked-value="0"
:disabled="form.hidden===1">
{{$root.translation('ID_REQUIRED')}}
<b-button variant="outline-light"
v-b-tooltip="{title:$root.translation('ID_ATTRIBUTE_WILL_BE_REQUIRED_WHEN_EDITING_USER_SETTINGS'),placement:'right',variant:'warning',customClass:'custom-tooltip'}">
<b-icon icon="question-circle-fill"
aria-hidden="true"
variant="primary"/>
</b-button>
</b-form-checkbox>
<b-form-checkbox v-model="form.password"
value="1"
unchecked-value="0"
:disabled="form.hidden===1">
{{$root.translation('ID_TYPE_PASSWORD')}}
<b-button variant="outline-light"
v-b-tooltip="{title:$root.translation('ID_ATTRIBUTE_WILL_BE_HIDDEN_USING_PLACEHOLDER'),placement:'right',variant:'warning',customClass:'custom-tooltip'}">
<b-icon icon="question-circle-fill"
aria-hidden="true"
variant="primary"/>
</b-button>
</b-form-checkbox>
</b-form-group>
</b-col>
<b-col>
</b-col>
</b-row>
<b-row class="bv-row-flex-cols">
<b-col cols="6">
<b-form-group :label="$root.translation('ID_PROPERTIES')">
<b-form-radio v-model="form.option"
value="allUser"
class="mt-2">
{{$root.translation('ID_ALL_USERS')}}
</b-form-radio>
<b-form-radio v-model="form.option"
value="byRol"
class="mt-3">
{{$root.translation('ID_BY_ROLE')}}
</b-form-radio>
</b-form-group>
</b-col>
<b-col cols="6" align-self="end">
<b-form-group>
<b-input-group>
<b-form-select v-model="form.rol"
:disabled="form.option==='allUser'"
:options="roles"></b-form-select>
<b-input-group-append>
<b-button variant="outline-secondary"
@click="refreshRoles"
:disabled="form.option==='allUser'">
<b-icon icon="arrow-repeat"
aria-hidden="true"/>
</b-button>
</b-input-group-append>
<b-input-group-append>
<b-button variant="success"
@click="addRole"
:disabled="form.option==='allUser'">
<b-icon icon="plus" aria-hidden="true"/> {{$root.translation('ID_ADD')}}
</b-button>
</b-input-group-append>
</b-input-group>
</b-form-group>
</b-col>
</b-row>
<b-row>
<b-col>
<b-form-group>
<b-form-tags v-model="form.selectedRoles"
style="min-height:55px"
:disabled="form.option==='allUser'">
<template v-slot="{ tags, inputAttrs, inputHandlers, tagVariant, addTag, removeTag, disabled}">
<!--important is the control body-->
<div class="d-inline-block">
<div v-for="tag in tags"
:key="tag"
:title="tag"
class="d-inline-block border bg-light rounded-lg p-1 mr-2">
{{getTextRol(tag)}}
<b-button size="sm"
variant="light"
:disabled="disabled"
@click="deleteRol(tag,function(){removeTag(tag);})">
<b-icon icon="x"
aria-hidden="true"
variant="primary"/>
</b-button>
</div>
</div>
</template>
</b-form-tags>
</b-form-group>
</b-col>
</b-row>
<b-row class="text-right">
<b-col>
<b-form-group>
<b-button variant="danger"
@click="$emit('cancel')">{{$root.translation('ID_CANCEL')}}</b-button>&nbsp;
<b-button type="submit"
variant="success"
:disabled="!statusValidation">{{$root.translation('ID_SAVE')}}</b-button>
</b-form-group>
</b-col>
</b-row>
</b-container>
</b-form>
</div>
</template>
<script>
import titleSection from "./titleSection.vue"
import axios from "axios"
import { validationMixin } from "vuelidate"
export default {
mixins: [validationMixin],
components: {
titleSection
},
data() {
return {
form: {
id: "",
name: "",
attributeId: "",
hidden: 0,
required: 0,
password: 0,
option: "allUser",
selectedRoles: [],
rol: "0"
},
roles: this.getRoles(),
statusValidation: true,
statusName: null,
statusNameMessage: "",
statusAttributeId: null,
statusAttributeIdMessage: ""
};
},
methods: {
reset() {
this.form = {
id: "",
name: "",
attributeId: "",
hidden: 0,
required: 0,
password: 0,
option: "allUser",
selectedRoles: [],
rol: "0"
};
this.statusValidation = true;
},
onsubmit() {
this.statusName = true;
if (this.form.name.trim() === "") {
this.statusName = false;
this.statusNameMessage = this.$root.translation("ID_IS_REQUIRED");
return;
}
this.statusAttributeId = true;
if (this.form.attributeId.trim() === "") {
this.statusAttributeId = false;
this.statusAttributeIdMessage = this.$root.translation("ID_IS_REQUIRED");
return;
}
if (/^[a-zA-Z][_0-9a-zA-Z]+$/.test(this.form.attributeId) === false) {
this.statusAttributeId = false;
this.statusAttributeIdMessage = this.$root.translation("ID_INVALID_DATA");
return;
}
this.saveForm();
},
validateName() {
this.statusValidation = false;
let formData = new FormData();
formData.append("id", this.form.id);
formData.append("name", this.form.name);
return axios.post(this.$root.baseUrl() + "userExtendedAttributes/index?option=verifyName", formData)
.then(response => {
response;
if (response.data.valid === false) {
this.statusName = false;
this.statusNameMessage = response.data.message;
} else {
this.statusName = true;
this.statusValidation = true;
}
})
.catch(error => {
error;
})
.finally(() => {
});
},
validateAttributeId() {
this.statusValidation = false;
if (/^[a-zA-Z][_0-9a-zA-Z]+$/.test(this.form.attributeId) === false) {
this.statusAttributeId = false;
this.statusAttributeIdMessage = this.$root.translation("ID_INVALID_DATA");
return;
}
let formData = new FormData();
formData.append("id", this.form.id);
formData.append("attributeId", this.form.attributeId);
return axios.post(this.$root.baseUrl() + "userExtendedAttributes/index?option=verifyAttributeId", formData)
.then(response => {
response;
if (response.data.valid === false) {
this.statusAttributeId = false;
this.statusAttributeIdMessage = response.data.message;
} else {
this.statusAttributeId = true;
this.statusValidation = true;
}
})
.catch(error => {
error;
})
.finally(() => {
});
},
saveForm() {
this.statusValidation = false;
let formData = this.formToFormData(this.form);
return axios.post(this.$root.baseUrl() + "userExtendedAttributes/index?option=save", formData)
.then(response => {
response;
this.$emit("save");
this.statusValidation = true;
})
.catch(error => {
error;
})
.finally(() => {
});
},
getRoles() {
this.refreshRoles();
return this.roles;
},
refreshRoles() {
let formData = new FormData();
formData.append("request", "allRoles");
axios.post(this.$root.baseUrl() + "roles/roles_Ajax", formData)
.then(response => {
response;
let data = [
{value: "0", text: this.$root.translation('ID_EMPTY_TYPE')}
];
for (let i in response.data) {
data.push({
value: response.data[i].ROL_CODE,
text: response.data[i].ROL_NAME
});
}
this.roles = data;
})
.catch(error => {
error;
})
.finally(() => {
});
},
addRole() {
if (this.form.rol === "0") {
return;
}
let obj = this.form.selectedRoles.find(rol => rol === this.form.rol);
if (obj !== undefined) {
return;
}
this.form.selectedRoles.push(this.form.rol);
},
getTextRol(tag) {
let obj = this.roles.find(rol => rol.value === tag);
return obj.text;
},
deleteRol(tag, process) {
this.$bvModal.msgBoxConfirm(this.$root.translation('ID_THE_USER_ROLES_FOR_ATTRIBUTE_HAS_BEEN_DELETED_PLEASE_CONFIRM', ['']), {
title: " ", //is important because title disappear
hideHeaderClose: false,
okTitle: this.$root.translation('ID_CONFIRM'),
okVariant: "success",
cancelTitle: this.$root.translation('ID_CANCEL'),
cancelVariant: "danger"
}).then(value => {
if (value === false) {
return;
}
process();
}).catch(err => {
err;
});
},
formToFormData(form) {
let formData = new FormData();
formData.append("UEA_ID", form.id);
formData.append("UEA_NAME", form.name);
formData.append("UEA_ATTRIBUTE_ID", form.attributeId);
formData.append("UEA_HIDDEN", form.hidden);
formData.append("UEA_REQUIRED", form.required);
formData.append("UEA_PASSWORD", form.password);
formData.append("UEA_OPTION", form.option);
formData.append("UEA_ROLES", JSON.stringify(form.selectedRoles));
return formData;
},
rowToForm(row) {
let form = {
id: row.id,
name: row.name,
attributeId: row.attributeId,
hidden: row.hidden,
required: row.required,
password: row.password,
option: row.option,
selectedRoles: JSON.parse(row.roles)
};
return form;
},
load(row) {
this.form = this.rowToForm(row);
}
}
}
</script>
<style scoped>
.bv-row-flex-cols{
min-height:7rem;
}
</style>

View File

@@ -0,0 +1,18 @@
<template>
<div>
<h3 class="text-primary">
{{title}}
</h3>
</div>
</template>
<script>
export default{
props: {
title: String
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,179 @@
<template>
<div>
<titleSection :title="$root.translation('ID_USER_EXTENDED_ATTRIBUTES')"></titleSection>
<b-form-group class="float-right">
<b-button variant="success"
@click="newAttribute">
<b-icon icon="plus" aria-hidden="true"/> {{$root.translation('ID_NEW_ATTRIBUTE')}}
</b-button>
</b-form-group>
<v-server-table ref="vServerTable1"
:url="$root.baseUrl()+'userExtendedAttributes/index?option=list'"
:columns="columns"
:options="options">
<div slot="roles"
slot-scope="props">
{{formatingRoles(props.row.rolesLabel)}}
</div>
<div slot="owner"
slot-scope="props">
{{props.row.owner}}
<b-avatar :id="'as-b-avatar-tooltip-'+props.index"
size="sm"
class="float-right">
</b-avatar>
<b-tooltip :target="'as-b-avatar-tooltip-'+props.index"
triggers="hover"
custom-class="custom-tooltip"
placement="right"
variant="info">
<b-container fluid>
<b-row class="text-left">
<b-col>
{{props.row.usrUsername}}<br>
{{props.row.usrFirstname}} {{props.row.usrLastname}}<br>
{{props.row.usrEmail}}<br>
{{props.row.usrFax}}<br>
{{props.row.usrCellular}}<br>
{{props.row.usrTimeZone}}<br>
</b-col>
<b-col>
<b-avatar size="lg"
variant="dark">
</b-avatar>
</b-col>
</b-row>
</b-container>
</b-tooltip>
</div>
<div slot="icons"
slot-scope="props">
<b-button-group>
<b-button :title="$root.translation('ID_EDIT_ATTRIBUTE')"
v-b-tooltip.hover
variant="light"
@click="editAttribute(props.row)">
<b-icon icon="pencil-fill" aria-hidden="true" variant="info"/>
</b-button>
<b-button :title="$root.translation('ID_DELETE_ATTRIBUTE')"
v-b-tooltip.hover
variant="light"
@click="deleteAttribute(props.row)">
<b-icon icon="trash" aria-hidden="true" variant="danger"/>
</b-button>
</b-button-group>
</div>
</v-server-table>
</div>
</template>
<script>
import titleSection from "./titleSection.vue"
import axios from "axios"
export default {
components: {
titleSection
},
data() {
return {
columns: [
"name",
"attributeId",
"roles",
"owner",
"dateCreate",
"icons"
],
options: {
headings: {
name: this.$root.translation('ID_ATTRIBUTE_NAME'),
attributeId: this.$root.translation('ID_ATTRIBUTE'),
roles: this.$root.translation('ID_ROLE'),
owner: this.$root.translation('ID_OWNER'),
dateCreate: this.$root.translation('ID_PRO_CREATE_DATE'),
icons: ""
},
sortable: [
"name",
"attributeId",
"roles",
"dateCreate"
],
filterable: [
"name",
"attributeId",
"roles",
"dateCreate"
],
texts: {
filter: "",
filterPlaceholder: this.$root.translation("ID_EMPTY_SEARCH"),
count: this.$root.translation("ID_SHOWING_FROM_RECORDS_COUNT"),
noResults: this.$root.translation("ID_NO_MATCHING_RECORDS"),
loading: this.$root.translation("ID_LOADING_GRID")
},
perPage: "pageSize" in window ? window.pageSize : 5,
perPageValues: [],
requestFunction(data) {
data.start = (data.page - 1) * data.limit;
return axios.get(this.url, {params: data}, {}).catch(function (e) {
this.dispatch("error", e);
});
},
responseAdapter(data) {
return {
data: data.data.data,
count: data.data.count
};
}
}
};
},
methods: {
newAttribute() {
this.$emit("newAttribute");
},
editAttribute(row) {
this.$emit("editAttribute", row);
},
deleteAttribute(row) {
this.$bvModal.msgBoxConfirm(this.$root.translation('ID_THE_ATTRIBUTE_WILL_BE_DELETED_PLEASE_CONFIRM', [row.name]), {
title: " ", //is important because title disappear
hideHeaderClose: false,
okTitle: this.$root.translation('ID_CONFIRM'),
okVariant: "success",
cancelTitle: this.$root.translation('ID_CANCEL'),
cancelVariant: "danger"
}).then(value => {
if (value === false) {
return;
}
let formData = new FormData();
formData.append("option", "delete");
formData.append("id", row.id);
axios.post(this.$root.baseUrl() + "userExtendedAttributes/index", formData)
.then(response => {
response;
this.refresh();
})
.catch(error => {
error;
})
.finally(() => {
});
}).catch(err => {
err;
});
},
refresh() {
this.$refs.vServerTable1.refresh();
},
formatingRoles(rolesLabel) {
return rolesLabel.join(", ");
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,33 @@
import Vue from 'vue'
import {BootstrapVue, IconsPlugin} from 'bootstrap-vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
import {ClientTable} from 'vue-tables-2'
import {ServerTable} from 'vue-tables-2'
import App from './App.vue';
Vue.config.productionTip = false
Vue.use(BootstrapVue)
Vue.use(IconsPlugin)
Vue.use(ClientTable, {}, false, 'bootstrap4', {});
Vue.use(ServerTable, {}, false, 'bootstrap4', {});
new Vue({
render: h => h(App),
methods: {
translation(text, params) {
if ("TRANSLATIONS" in window && text in window.TRANSLATIONS) {
text = window.TRANSLATIONS[text];
if (params != undefined && "length" in params) {
for (let i = 0; i < params.length; i++) {
text = text.replace("{" + i + "}", params[i]);
}
}
}
return text;
},
baseUrl() {
return "../";
}
}
}).$mount('#app');

View File

@@ -0,0 +1,3 @@
module.exports = {
publicPath: '/lib/userExtendedAttributes/'
};

View File

@@ -0,0 +1,24 @@
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
/nbproject/private/

View File

@@ -0,0 +1,24 @@
# my-app
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).

View File

@@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

View File

@@ -0,0 +1,17 @@
<?php
global $G_PUBLISH;
$G_PUBLISH = new Publisher();
try {
$lang = defined("SYS_LANG") ? SYS_LANG : "en";
$html = file_get_contents(PATH_HTML . "lib/userPersonalInformation/index.html");
$html = str_replace("translation.en.js", "translation.{$lang}.js", $html);
echo $html;
} catch (Exception $e) {
$message = [
'MESSAGE' => $e->getMessage()
];
$G_PUBLISH->AddContent('xmlform', 'xmlform', 'login/showMessage', '', $message);
G::RenderPage('publish', 'blank');
}

View File

@@ -0,0 +1,4 @@
file.reference.userPersonalInformation-public=public
files.encoding=UTF-8
site.root.folder=${file.reference.userPersonalInformation-public}
source.folder=

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.web.clientproject</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/clientside-project/1">
<name>userPersonalInformation</name>
</data>
</configuration>
</project>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,51 @@
{
"name": "userPersonalInformation",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build --dest ../../../public_html/lib/userPersonalInformation",
"lint": "vue-cli-service lint"
},
"dependencies": {
"@panter/vue-i18next": "^0.15.2",
"@vue/cli": "^4.4.6",
"axios": "^0.19.2",
"bootstrap": "^4.5.0",
"bootstrap-vue": "^2.20.1",
"core-js": "^3.8.1",
"lodash": "^4.17.19",
"save": "^2.4.0",
"vue": "^2.6.11",
"vue-tables-2": "^2.1.61",
"vuelidate": "^0.7.5"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^4.5.9",
"@vue/cli-plugin-eslint": "^4.5.9",
"@vue/cli-service": "^4.5.9",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"vue-template-compiler": "^2.6.11"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<!-- These are default values, then they are overridden when processmaker runs -->
<script type="text/javascript" src="/js/ext/translation.en.js"></script>
<script type="text/javascript">
var USR_UID='';
</script>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@@ -0,0 +1,39 @@
<template>
<div id="app">
<personalInformation refs="personalInformation"></personalInformation>
</div>
</template>
<script>
import personalInformation from "./components/personalInformation.vue"
export default {
name: 'app',
components: {
personalInformation
},
data() {
return {
views: {
personalInformation: true
}
};
},
methods: {
showView(name) {
for (let view in this.views) {
this.views[view] = false;
}
this.views[name] = true;
}
}
}
</script>
<style>
#app {
margin: 20px;
}
.custom-tooltip > .tooltip-inner{
max-width: none;
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@@ -0,0 +1,885 @@
<template>
<div>
<titleSection :title="$root.translation('ID_PERSONAL_INFORMATION')"></titleSection>
<b-form @submit.stop.prevent="onsubmit">
<b-container fluid>
<b-row>
<b-col cols="3">
<b-form-group :label="$root.translation('ID_FIRSTNAME')+' (*)'">
<b-form-input v-model="form.USR_FIRSTNAME"
autocomplete="off"
:state="validateState('USR_FIRSTNAME')"></b-form-input>
<b-form-invalid-feedback>{{$root.translation('ID_IS_REQUIRED')}}</b-form-invalid-feedback>
</b-form-group>
</b-col>
<b-col cols="2">
</b-col>
<b-col cols="3">
<b-form-group :label="$root.translation('ID_LASTNAME')+' (*)'">
<b-form-input v-model="form.USR_LASTNAME"
autocomplete="off"
:state="validateState('USR_LASTNAME')"></b-form-input>
<b-form-invalid-feedback>{{$root.translation('ID_IS_REQUIRED')}}</b-form-invalid-feedback>
</b-form-group>
</b-col>
<b-col cols="1">
</b-col>
<b-col cols="3">
<b-avatar rounded
size="5rem"
button
badge-variant="light"
style="position: absolute;right:30px;">
</b-avatar>
</b-col>
</b-row>
<b-row>
<b-col cols="3">
<b-form-group :label="$root.translation('ID_ADDRESS')">
<b-form-input v-model="form.USR_ADDRESS"
autocomplete="off"/>
</b-form-group>
</b-col>
<b-col cols="2">
</b-col>
<b-col cols="3">
<b-form-group :label="$root.translation('ID_ZIP_CODE')">
<b-form-input v-model="form.USR_ZIP_CODE"
autocomplete="off"/>
</b-form-group>
</b-col>
<b-col cols="1">
</b-col>
<b-col cols="3">
<b-form-group :label="$root.translation('ID_USERNAME')+' (*)'">
<b-form-input v-model="form.USR_USERNAME"
autocomplete="off"
:state="validate.USR_USERNAME.state"
@keyup="validateUserName"></b-form-input>
<b-form-valid-feedback><span v-html="validate.USR_USERNAME.message"></span></b-form-valid-feedback>
<b-form-invalid-feedback><span v-html="validate.USR_USERNAME.message"></span></b-form-invalid-feedback>
</b-form-group>
</b-col>
</b-row>
<b-row>
<b-col cols="3">
<b-form-group :label="$root.translation('ID_COUNTRY')">
<b-form-select v-model="form.USR_COUNTRY"
:options="countryList"
@change="getStateList"/>
</b-form-group>
</b-col>
<b-col cols="2">
<b-form-group :label="$root.translation('ID_STATE_REGION')">
<b-form-select v-model="form.USR_CITY"
:options="stateList"
@change="getLocationList"/>
</b-form-group>
</b-col>
<b-col cols="3">
<b-form-group :label="$root.translation('ID_CITY')">
<b-form-select v-model="form.USR_LOCATION"
:options="locationList"/>
</b-form-group>
</b-col>
<b-col cols="1">
</b-col>
<b-col cols="3">
<b-form-group :label="$root.translation('ID_EMAIL')+' (*)'">
<b-form-input v-model="form.USR_EMAIL"
autocomplete="off"
:state="validateState('USR_EMAIL')"></b-form-input>
<b-form-invalid-feedback>{{$root.translation('ID_EMAIL_ENTER_VALID')}}</b-form-invalid-feedback>
</b-form-group>
</b-col>
</b-row>
<b-row>
<b-col cols="3">
<b-form-group :label="$root.translation('ID_PHONE')">
<b-form-input v-model="form.USR_PHONE"
autocomplete="off"/>
</b-form-group>
</b-col>
<b-col cols="2">
</b-col>
<b-col cols="3">
<b-form-group :label="$root.translation('ID_POSITION')">
<b-form-input v-model="form.USR_POSITION"
autocomplete="off"/>
</b-form-group>
</b-col>
<b-col cols="1">
</b-col>
<b-col cols="3">
<b-form-group :label="$root.translation('ID_STATUS')">
<b-form-select v-model="form.USR_STATUS"
:options="userStatus"/>
</b-form-group>
</b-col>
</b-row>
<b-row>
<b-col cols="3">
<b-form-group :label="$root.translation('ID_REPLACED_BY')">
<b-input-group>
<b-input-group-prepend class="w-25">
<b-form-input v-model="filterUser"
autocomplete="off"
@keyup="getUsersList"
placeholder="search"></b-form-input>
</b-input-group-prepend>
<b-form-select v-model="form.USR_REPLACED_BY"
:options="usersList"></b-form-select>
</b-input-group>
</b-form-group>
</b-col>
<b-col cols="2"></b-col>
<b-col cols="3">
<b-form-group :label="$root.translation('ID_CALENDAR')">
<b-form-select v-model="form.USR_CALENDAR"
:options="availableCalendars"/>
</b-form-group>
</b-col>
<b-col cols="1">
</b-col>
<b-col cols="3">
<b-form-group :label="$root.translation('ID_EXPIRATION_DATE')">
<b-form-datepicker v-model="form.USR_DUE_DATE"
:date-format-options="{year:'numeric',month:'numeric',day:'numeric'}"/>
</b-form-group>
</b-col>
</b-row>
<b-row>
<b-col cols="3">
<b-form-group :label="$root.translation('ID_TIME_ZONE')">
<b-form-select v-model="form.USR_TIME_ZONE"
:options="timeZoneList"/>
</b-form-group>
</b-col>
<b-col cols="2">
</b-col>
<b-col cols="3">
<b-form-group :label="$root.translation('ID_DEFAULT_LANGUAGE')">
<b-form-select v-model="form.USR_DEFAULT_LANG"
:options="languagesList"/>
</b-form-group>
</b-col>
<b-col cols="1">
</b-col>
<b-col cols="3">
<b-form-group :label="$root.translation('ID_ROLE')">
<b-form-select v-model="form.USR_ROLE"
:options="rolesList"/>
</b-form-group>
</b-col>
</b-row>
<b-row>
<b-col cols="3">
<b-form-group :label="$root.translation('ID_DEFAULT_MAIN_MENU_OPTION')">
<b-form-select v-model="form.PREF_DEFAULT_MENUSELECTED"
:options="defaultMainMenuOptionList"/>
</b-form-group>
</b-col>
<b-col cols="2">
</b-col>
<b-col cols="3">
<b-form-group :label="$root.translation('ID_DEFAULT_CASES_MENU_OPTION')">
<b-form-select v-model="form.PREF_DEFAULT_CASES_MENUSELECTED"
:options="defaultCasesMenuOptionList"/>
</b-form-group>
</b-col>
<b-col cols="1">
</b-col>
<b-col cols="3">
<b-form-group :label="$root.translation('ID_NEW_PASSWORD')+' (*)'">
<b-form-input v-model="form.USR_NEW_PASS"
autocomplete="off"
:state="validate.USR_NEW_PASS.state"
type="password"
@keyup="validatePassword"></b-form-input>
<b-form-valid-feedback><span v-html="validate.USR_NEW_PASS.message"></span></b-form-valid-feedback>
<b-form-invalid-feedback><span v-html="validate.USR_NEW_PASS.message"></span></b-form-invalid-feedback>
</b-form-group>
</b-col>
</b-row>
<b-row>
<b-col cols="3"></b-col>
<b-col cols="2"></b-col>
<b-col cols="3"></b-col>
<b-col cols="1"></b-col>
<b-col cols="3">
<b-form-group :label="$root.translation('ID_CONFIRM_PASSWORD')+' (*)'">
<b-form-input v-model="form.USR_CNF_PASS"
autocomplete="off"
:state="validate.USR_CNF_PASS.state"
type="password"
@keyup="validateConfirmationPassword"></b-form-input>
<b-form-invalid-feedback><span v-html="validate.USR_CNF_PASS.message"></span></b-form-invalid-feedback>
</b-form-group>
</b-col>
</b-row>
<b-row>
<b-col cols="8">
<fieldset class="border pt-1 pl-3 pb-3 pr-3">
<legend style="width:auto;">{{$root.translation('ID_EXTENDED_ATTRIBUTES')}}</legend>
<b-container class="mb-3">
<b-row>
<b-col>
<div v-for="userExtendedAttribute in userExtendedAttributesList"
:key="userExtendedAttribute.id">
<b-form-group :label="userExtendedAttribute.name+(userExtendedAttribute.required===1?' (*)':'')"
v-if="userExtendedAttribute.hidden===0?true:false">
<b-form-input v-model="form.USR_EXTENDED_ATTRIBUTES_DATA[userExtendedAttribute.attributeId]"
autocomplete="off"
:type="userExtendedAttribute.password===1?'password':'text'"
:state="validateExtendedAttribute(userExtendedAttribute)"></b-form-input>
<b-form-invalid-feedback>{{$root.translation('ID_IS_REQUIRED')}}</b-form-invalid-feedback>
</b-form-group>
</div>
</b-col>
</b-row>
</b-container>
</fieldset>
</b-col>
<b-col cols="4">
<fieldset class="border pt-1 pl-3 pb-3 pr-3">
<legend style="width:auto;">{{$root.translation('ID_COSTS')}}</legend>
<b-form-group :label="$root.translation('ID_COST_BY_HOUR')">
<b-form-input v-model="form.USR_COST_BY_HOUR"
autocomplete="off"
:state="validateState('USR_COST_BY_HOUR')"></b-form-input>
<b-form-invalid-feedback>{{$root.translation('ID_INVALID_VALUE',[$root.translation('ID_COST_BY_HOUR')])}}</b-form-invalid-feedback>
</b-form-group>
<b-form-group :label="$root.translation('ID_UNITS')">
<b-form-input v-model="form.USR_UNIT_COST"
autocomplete="off"/>
</b-form-group>
</fieldset>
</b-col>
</b-row>
<b-row>
<b-col cols="12">
<b-form-group class="mt-4">
<b-form-checkbox v-model="form.USR_LOGGED_NEXT_TIME"
value="1"
unchecked-value="0">
{{$root.translation('ID_USER_MUST_CHANGE_PASSWORD_AT_NEXT_LOGON')}}
</b-form-checkbox>
</b-form-group>
</b-col>
</b-row>
<b-row>
<b-col cols="12">
<b-form-group class="mt-4 float-right">
<b-button variant="danger"
@click="cancel">{{$root.translation('ID_CANCEL')}}</b-button>&nbsp;
<b-button type="submit"
variant="success"
:disabled="disableButtonSave">{{$root.translation('ID_SAVE')}}</b-button>
</b-form-group>
</b-col>
</b-row>
</b-container>
</b-form>
</div>
</template>
<script>
import titleSection from "./titleSection.vue"
import axios from "axios"
import { validationMixin } from "vuelidate"
import { required, numeric, email } from "vuelidate/lib/validators"
export default {
mixins: [validationMixin],
components: {
titleSection
},
validations: {
form: {
USR_FIRSTNAME: {
required
},
USR_LASTNAME: {
required
},
USR_EMAIL: {
required,
email
},
USR_COST_BY_HOUR: {
numeric
}
}
},
data() {
return {
form: {
USR_UID: "",
USR_FIRSTNAME: "",
USR_LASTNAME: "",
USR_ADDRESS: "",
USR_ZIP_CODE: "",
USR_COUNTRY: "",
USR_CITY: "",
USR_LOCATION: "",
USR_USERNAME: "",
USR_PHONE: "",
USR_POSITION: "",
USR_EMAIL: "",
USR_REPLACED_BY: "",
USR_CALENDAR: "",
USR_STATUS: "ACTIVE",
USR_TIME_ZONE: "",
USR_DEFAULT_LANG: "",
USR_DUE_DATE: this.getDefaultDueDate(),
PREF_DEFAULT_MENUSELECTED: "PM_SETUP",
PREF_DEFAULT_CASES_MENUSELECTED: "",
USR_ROLE: "PROCESSMAKER_OPERATOR",
USR_COST_BY_HOUR: "0",
USR_UNIT_COST: "$",
USR_NEW_PASS: "",
USR_CNF_PASS: "",
USR_LOGGED_NEXT_TIME: "0",
//
USR_EXTENDED_ATTRIBUTES_DATA: []
},
validate: {
USR_USERNAME: {
message: "",
state: true
},
USR_NEW_PASS: {
message: "",
state: true
},
USR_CNF_PASS: {
message: "",
state: true
}
},
countryList: [{
value: "",
text: this.$root.translation('ID_SELECT')
}],
stateList: [{
value: "",
text: this.$root.translation('ID_SELECT')
}],
locationList: [{
value: "",
text: this.$root.translation('ID_SELECT')
}],
usersList: [],
filterUser: "",
availableCalendars: [],
userStatus: [
{value: "ACTIVE", text: this.$root.translation("ID_ACTIVE")},
{value: "INACTIVE", text: this.$root.translation("ID_INACTIVE")},
{value: "VACATION", text: this.$root.translation("ID_VACATION")}
],
timeZoneList: [],
languagesList: [],
defaultMainMenuOptionList: [],
defaultCasesMenuOptionList: [],
rolesList: [],
userExtendedAttributesList: [],
disableButtonSave: false,
editing: false
};
},
mounted() {
this.$nextTick(function () {
let promise = null;
if ("USR_UID" in window && window.USR_UID !== "") {
promise = this.load();
promise.then(response => {
response;
this.loadServices();
});
} else {
this.loadServices();
}
});
},
methods: {
cancel() {
window.location = this.$root.baseUrl() + "users/users_List";
},
onsubmit() {
this.$v.form.$touch();
if (this.$v.form.$anyError) {
return;
}
if (this.form.USR_UID === "") {
if (this.form.USR_NEW_PASS === "") {
this.validate.USR_NEW_PASS.message = this.$root.translation('ID_IS_REQUIRED');
this.validate.USR_NEW_PASS.state = false;
this.disableButtonSave = true;
return;
}
if (this.form.USR_CNF_PASS === "") {
this.validate.USR_CNF_PASS.message = this.$root.translation('ID_IS_REQUIRED');
this.validate.USR_CNF_PASS.state = false;
this.disableButtonSave = true;
return;
}
if (this.form.USR_CNF_PASS !== this.form.USR_NEW_PASS) {
this.validate.USR_CNF_PASS.message = this.$root.translation("ID_NEW_PASS_SAME_OLD_PASS");
this.validate.USR_CNF_PASS.state = false;
this.disableButtonSave = true;
return;
}
}
for (let i in this.userExtendedAttributesList) {
let status = this.validateExtendedAttribute(this.userExtendedAttributesList[i]);
if (this.userExtendedAttributesList[i].required === 1) {
if (status === null || status === false) {
return;
}
}
}
//get form data
let extendedAttributes = {};
for (let i in this.userExtendedAttributesList) {
let attributeId = this.userExtendedAttributesList[i].attributeId;
let value = this.form.USR_EXTENDED_ATTRIBUTES_DATA[attributeId];
if (value !== undefined) {
extendedAttributes[attributeId] = value;
}
}
let formData = new FormData();
formData.append("_token", "EE2sNzIAdIYNLJE8UQY2Qj7CyewqtPkMRusDviix");
formData.append("USR_FIRSTNAME", this.form.USR_FIRSTNAME);
formData.append("USR_LASTNAME", this.form.USR_LASTNAME);
formData.append("USR_USERNAME", this.form.USR_USERNAME);
formData.append("USR_EMAIL", this.form.USR_EMAIL);
formData.append("USR_ADDRESS", this.form.USR_ADDRESS);
formData.append("USR_ZIP_CODE", this.form.USR_ZIP_CODE);
formData.append("USR_COUNTRY", this.form.USR_COUNTRY);
formData.append("USR_CITY", this.form.USR_CITY);
formData.append("USR_REGION", this.form.USR_CITY); //important for compatibility
formData.append("USR_LOCATION", this.form.USR_LOCATION);
formData.append("USR_PHONE", this.form.USR_PHONE);
formData.append("USR_POSITION", this.form.USR_POSITION);
formData.append("USR_REPLACED_BY", this.form.USR_REPLACED_BY);
formData.append("USR_DUE_DATE", this.form.USR_DUE_DATE);
formData.append("USR_CALENDAR", this.form.USR_CALENDAR);
formData.append("USR_STATUS", this.form.USR_STATUS);
formData.append("USR_ROLE", this.form.USR_ROLE);
formData.append("USR_TIME_ZONE", this.form.USR_TIME_ZONE);
formData.append("USR_DEFAULT_LANG", this.form.USR_DEFAULT_LANG);
formData.append("USR_COST_BY_HOUR", this.form.USR_COST_BY_HOUR);
formData.append("USR_UNIT_COST", this.form.USR_UNIT_COST);
formData.append("currentPassword", "");
formData.append("USR_NEW_PASS", this.form.USR_NEW_PASS);
formData.append("USR_CNF_PASS", this.form.USR_CNF_PASS);
formData.append("USR_PHOTO", "");
formData.append("PREF_DEFAULT_MENUSELECTED", this.form.PREF_DEFAULT_MENUSELECTED);
formData.append("PREF_DEFAULT_CASES_MENUSELECTED", this.form.PREF_DEFAULT_CASES_MENUSELECTED);
formData.append("action", "saveUser");
formData.append("USR_UID", this.form.USR_UID);
formData.append("USR_LOGGED_NEXT_TIME", this.form.USR_LOGGED_NEXT_TIME);
formData.append("USR_EXTENDED_ATTRIBUTES_DATA", JSON.stringify(extendedAttributes));
axios.post(this.$root.baseUrl() + "users/usersAjax", formData)
.then(response => {
response;
if ("error" in response.data && response.data.error !== "") {
this.$bvModal.msgBoxOk(response.data.error, {
title: " ", //is important because title disappear
hideHeaderClose: false,
okTitle: this.$root.translation('ID_OK'),
okVariant: "success",
okOnly: true
}).then(value => {
if (value === false) {
return;
}
}).catch(err => {
err;
});
}
window.location = this.$root.baseUrl() + "users/users_List";
})
.catch(error => {
error;
})
.finally(() => {
});
},
validateState(name) {
const {$dirty, $error} = this.$v.form[name];
return $dirty ? !$error : null;
},
validateUserName() {
this.disableButtonSave = true;
let formData = new FormData();
formData.append("action", "testUsername");
formData.append("USR_UID", this.form.USR_UID);
formData.append("NEW_USERNAME", this.form.USR_USERNAME);
return axios.post(this.$root.baseUrl() + "users/usersAjax", formData)
.then(response => {
response;
this.validate.USR_USERNAME.message = response.data.descriptionText;
if (response.data.exists === false) {
this.validate.USR_USERNAME.state = true;
this.disableButtonSave = false;
return;
}
this.validate.USR_USERNAME.state = false;
this.disableButtonSave = true;
})
.catch(error => {
error;
})
.finally(() => {
});
},
validatePassword() {
this.disableButtonSave = true;
let formData = new FormData();
formData.append("action", "testPassword");
formData.append("PASSWORD_TEXT", this.form.USR_NEW_PASS);
return axios.post(this.$root.baseUrl() + "users/usersAjax", formData)
.then(response => {
response;
this.validate.USR_NEW_PASS.message = response.data.DESCRIPTION;
if (response.data.STATUS === true) {
this.validate.USR_NEW_PASS.state = true;
this.disableButtonSave = false;
return;
}
this.validate.USR_NEW_PASS.state = false;
this.disableButtonSave = true;
})
.catch(error => {
error;
})
.finally(() => {
});
},
validateConfirmationPassword() {
this.disableButtonSave = true;
this.validate.USR_CNF_PASS.message = this.$root.translation("ID_NEW_PASS_SAME_OLD_PASS");
if (this.form.USR_CNF_PASS === this.form.USR_NEW_PASS) {
this.validate.USR_CNF_PASS.state = true;
this.disableButtonSave = false;
return;
}
this.validate.USR_CNF_PASS.state = false;
this.disableButtonSave = true;
},
validateExtendedAttribute(obj) {
let value = this.form.USR_EXTENDED_ATTRIBUTES_DATA[obj.attributeId];
if (obj.required === 1) {
if (value === undefined || value === "") {
return false;
}
return true;
}
return null;
},
load() {
let formData = new FormData();
formData.append("action", "userData");
formData.append("USR_UID", window.USR_UID);
return axios.post(this.$root.baseUrl() + "users/usersAjax", formData)
.then(response => {
response;
if ("user" in response.data) {
for (let i in this.form) {
if (i in response.data.user) {
let value = response.data.user[i]
if (i === "USR_EXTENDED_ATTRIBUTES_DATA") {
if (value === null) {
value = "{}";
}
value = JSON.parse(value);
}
this.form[i] = value;
}
}
}
})
.catch(error => {
error;
})
.finally(() => {
});
},
loadServices() {
this.getCountryList();
this.getAvailableCalendars();
this.getTimeZoneList();
this.getLanguagesList();
this.getDefaultMainMenuOptionList();
this.getDefaultCasesMenuOptionList();
this.getRolesList();
this.getUserExtendedAttributesList();
},
getCountryList() {
let formData = new FormData();
formData.append("action", "countryList");
return axios.post(this.$root.baseUrl() + "users/usersAjax", formData)
.then(response => {
response;
let data = [{
value: "",
text: this.$root.translation('ID_SELECT')
}];
for (let i in response.data) {
data.push({
value: response.data[i].IC_UID,
text: response.data[i].IC_NAME
});
}
this.countryList = data;
this.getStateList();
})
.catch(error => {
error;
})
.finally(() => {
});
},
getStateList() {
let formData = new FormData();
formData.append("action", "stateList");
formData.append("IC_UID", this.form.USR_COUNTRY);
return axios.post(this.$root.baseUrl() + "users/usersAjax", formData)
.then(response => {
response;
let data = [{
value: "",
text: this.$root.translation('ID_SELECT')
}];
for (let i in response.data) {
data.push({
value: response.data[i].IS_UID,
text: response.data[i].IS_NAME
});
}
this.stateList = data;
this.getLocationList();
})
.catch(error => {
error;
})
.finally(() => {
});
},
getLocationList() {
let formData = new FormData();
formData.append("action", "locationList");
formData.append("IC_UID", this.form.USR_COUNTRY);
formData.append("IS_UID", this.form.USR_CITY);
return axios.post(this.$root.baseUrl() + "users/usersAjax", formData)
.then(response => {
response;
let data = [{
value: "",
text: this.$root.translation('ID_SELECT')
}];
for (let i in response.data) {
data.push({
value: response.data[i].IL_UID,
text: response.data[i].IL_NAME
});
}
this.locationList = data;
})
.catch(error => {
error;
})
.finally(() => {
});
},
getUsersList() {
let formData = new FormData();
formData.append("action", "usersList");
formData.append("USR_UID", this.form.USR_UID);
formData.append("filter", this.filterUser);
return axios.post(this.$root.baseUrl() + "users/usersAjax", formData)
.then(response => {
response;
let data = [];
for (let i in response.data) {
data.push({
value: response.data[i].USR_UID,
text: response.data[i].USER_FULLNAME
});
}
this.usersList = data;
//set the first element
if (data.length > 0) {
this.form.USR_REPLACED_BY = data[0].value;
} else {
this.form.USR_REPLACED_BY = "";
}
})
.catch(error => {
error;
})
.finally(() => {
});
},
getAvailableCalendars() {
let formData = new FormData();
formData.append("action", "availableCalendars");
return axios.post(this.$root.baseUrl() + "users/usersAjax", formData)
.then(response => {
response;
let data = [];
for (let i in response.data) {
data.push({
value: response.data[i].CALENDAR_UID,
text: response.data[i].CALENDAR_NAME
});
}
this.availableCalendars = data;
})
.catch(error => {
error;
})
.finally(() => {
});
},
getTimeZoneList() {
let formData = new FormData();
formData.append("action", "timeZoneParameters");
return axios.post(this.$root.baseUrl() + "users/usersAjax", formData)
.then(response => {
response;
let data = [];
for (let i in response.data.timeZoneList) {
data.push({
value: response.data.timeZoneList[i].value,
text: response.data.timeZoneList[i].text
});
}
this.timeZoneList = data;
this.form.USR_TIME_ZONE = response.data.systemTimeZone;
})
.catch(error => {
error;
})
.finally(() => {
});
},
getLanguagesList() {
let formData = new FormData();
formData.append("action", "languagesList");
return axios.post(this.$root.baseUrl() + "users/usersAjax", formData)
.then(response => {
response;
let data = [];
for (let i in response.data) {
data.push({
value: response.data[i].LAN_ID,
text: response.data[i].LAN_NAME
});
}
this.languagesList = data;
})
.catch(error => {
error;
})
.finally(() => {
});
},
getDefaultMainMenuOptionList() {
let formData = new FormData();
formData.append("action", "defaultMainMenuOptionList");
return axios.post(this.$root.baseUrl() + "users/usersAjax", formData)
.then(response => {
response;
let data = [];
for (let i in response.data) {
data.push({
value: response.data[i].id,
text: response.data[i].name
});
}
this.defaultMainMenuOptionList = data;
})
.catch(error => {
error;
})
.finally(() => {
});
},
getDefaultCasesMenuOptionList() {
let formData = new FormData();
formData.append("action", "defaultCasesMenuOptionList");
return axios.post(this.$root.baseUrl() + "users/usersAjax", formData)
.then(response => {
response;
let data = [{
value: "",
text: this.$root.translation('ID_SELECT')
}];
for (let i in response.data) {
data.push({
value: response.data[i].id,
text: response.data[i].name
});
}
this.defaultCasesMenuOptionList = data;
})
.catch(error => {
error;
})
.finally(() => {
});
},
getRolesList() {
let formData = new FormData();
formData.append("action", "rolesList");
return axios.post(this.$root.baseUrl() + "users/usersAjax", formData)
.then(response => {
response;
let data = [];
for (let i in response.data) {
data.push({
value: response.data[i].ROL_UID,
text: response.data[i].ROL_CODE
});
}
this.rolesList = data;
})
.catch(error => {
error;
})
.finally(() => {
});
},
getUserExtendedAttributesList() {
let formData = new FormData();
formData.append("option", "userExtendedAttributesList");
return axios.post(this.$root.baseUrl() + "userExtendedAttributes/index", formData)
.then(response => {
response;
this.userExtendedAttributesList = response.data.data;
})
.catch(error => {
error;
})
.finally(() => {
});
},
getDefaultDueDate() {
let date = new Date();
let month = "" + (date.getMonth() + 1);
let day = "" + date.getDate();
let year = date.getFullYear();
if (month.length < 2)
month = "0" + month;
if (day.length < 2)
day = "0" + day;
return [year + 1, month, day].join("-");
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,18 @@
<template>
<div>
<h3 class="text-primary">
{{title}}
</h3>
</div>
</template>
<script>
export default{
props: {
title: String
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,33 @@
import Vue from 'vue'
import {BootstrapVue, IconsPlugin} from 'bootstrap-vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
import {ClientTable} from 'vue-tables-2'
import {ServerTable} from 'vue-tables-2'
import App from './App.vue';
Vue.config.productionTip = false
Vue.use(BootstrapVue)
Vue.use(IconsPlugin)
Vue.use(ClientTable, {}, false, 'bootstrap4', {});
Vue.use(ServerTable, {}, false, 'bootstrap4', {});
new Vue({
render: h => h(App),
methods: {
translation(text, params) {
if ("TRANSLATIONS" in window && text in window.TRANSLATIONS) {
text = window.TRANSLATIONS[text];
if (params != undefined && "length" in params) {
for (let i = 0; i < params.length; i++) {
text = text.replace("{" + i + "}", params[i]);
}
}
}
return text;
},
baseUrl() {
return "../";
}
}
}).$mount('#app');

View File

@@ -0,0 +1,3 @@
module.exports = {
publicPath: '/lib/userPersonalInformation/'
};

View File

@@ -14,6 +14,18 @@ try {
// Executing the action
switch ($action) {
case 'timeZoneParameters':
$arraySystemConfiguration = System::getSystemConfiguration('', '', config("system.workspace"));
$data = array_map(function ($value) {
return ["value" => $value, "text" => $value];
}, DateTimeZone::listIdentifiers());
$result = [
"timeZoneList" => $data,
"systemTimeZone" => $arraySystemConfiguration['time_zone']
];
print(G::json_encode($result));
break;
case 'countryList':
$c = new Criteria();
$c->add(IsoCountryPeer::IC_UID, null, Criteria::ISNOTNULL);
@@ -200,9 +212,6 @@ try {
} catch (Exception $e) {
$result->success = false;
$result->fileError = true;
echo G::json_encode($result);
exit(0);
}
}
@@ -422,7 +431,7 @@ try {
$fields['DESCRIPTION'] = G::LoadTranslation('ID_PASSWORD_COMPLIES_POLICIES') . '</span>';
$fields['STATUS'] = true;
}
$span = '<span style="color: ' . $color . '; font: 9px tahoma,arial,helvetica,sans-serif;">';
$span = '<span style="color: ' . $color . '; ">';
$gif = '<img width="13" height="13" border="0" src="' . $img . '">';
$fields['DESCRIPTION'] = $span . $gif . $fields['DESCRIPTION'];
print(G::json_encode($fields));
@@ -459,7 +468,7 @@ try {
$response['exists'] = false;
}
$span = '<span style="color: ' . $color . '; font: 9px tahoma,arial,helvetica,sans-serif;">';
$span = '<span style="color: ' . $color . '; ">';
$gif = '<img width="13" height="13" border="0" src="' . $img . '">';
$response['descriptionText'] = $span . $gif . $text . '</span>';
echo G::json_encode($response);

View File

@@ -9,6 +9,16 @@ if (isset($_GET['USR_UID']) && RBAC::isGuestUserUid($_GET['USR_UID'])) {
//calculating the max upload file size;
use ProcessMaker\Core\System;
if (isset($_REQUEST['userInterface']) && $_REQUEST['userInterface'] === "v2") {
$lang = defined("SYS_LANG") ? SYS_LANG : "en";
$html = file_get_contents(PATH_HTML . "lib/userPersonalInformation/index.html");
$html = str_replace("var USR_UID='';", "var USR_UID='{$_GET['USR_UID']}';", $html);
$html = str_replace("translation.en.js", "translation.{$lang}.js", $html);
echo $html;
exit();
}
$POST_MAX_SIZE = ini_get('post_max_size');
$mul = substr($POST_MAX_SIZE, - 1);
$mul = ($mul == 'M' ? 1048576 : ($mul == 'K' ? 1024 : ($mul == 'G' ? 1073741824 : 1)));
@@ -30,7 +40,7 @@ $expirationDate = 1;
$envFile = PATH_CONFIG . 'env.ini';
if (file_exists($envFile)) {
$sysConf = System::getSystemConfiguration($envFile);
if (isset($sysConf['expiration_year']) && $sysConf['expiration_year']>0) {
if (isset($sysConf['expiration_year']) && $sysConf['expiration_year'] > 0) {
$expirationDate = abs($sysConf['expiration_year']);
}
}
@@ -52,9 +62,9 @@ $oHeadPublisher->assign('MODE', $_GET['MODE']);
$oHeadPublisher->assign('MAX_FILES_SIZE', ' (' . $maxFileSize . ') ');
$oHeadPublisher->assign('SYSTEM_TIME_ZONE', $arraySystemConfiguration['time_zone']);
$oHeadPublisher->assign('TIME_ZONE_DATA', array_map(function ($value) {
return [$value, $value];
}, DateTimeZone::listIdentifiers()));
$oHeadPublisher->assign('__SYSTEM_UTC_TIME_ZONE__', (isset($_SESSION['__SYSTEM_UTC_TIME_ZONE__']) && $_SESSION['__SYSTEM_UTC_TIME_ZONE__'])? 1 : 0);
return [$value, $value];
}, DateTimeZone::listIdentifiers()));
$oHeadPublisher->assign('__SYSTEM_UTC_TIME_ZONE__', (isset($_SESSION['__SYSTEM_UTC_TIME_ZONE__']) && $_SESSION['__SYSTEM_UTC_TIME_ZONE__']) ? 1 : 0);
$oHeadPublisher->assign('EXPIRATION_DATE', $expirationDate);
$oHeadPublisher->assign('LANGUAGE_MANAGEMENT', $languageManagement);
$oHeadPublisher->assign('__ACTION__', 'saveUser');

View File

@@ -5,6 +5,15 @@ use ProcessMaker\Core\System;
$RBAC->requirePermissions('PM_USERS');
if (isset($_REQUEST['userInterface']) && $_REQUEST['userInterface'] === "v2") {
$lang = defined("SYS_LANG") ? SYS_LANG : "en";
$html = file_get_contents(PATH_HOME . "public_html/lib/userPersonalInformation/index.html");
$html = str_replace("translation.en.js", "translation.{$lang}.js", $html);
echo $html;
exit();
}
//calculating the max upload file size;
$POST_MAX_SIZE = ini_get('post_max_size');
$mul = substr($POST_MAX_SIZE, - 1);