Is there a way to restrict doc types by user role?
For instance, can I create a customization to allow certain users to only select the "Bill" type from the drop-down in the Bills and Adjustment screen of the Accounts Payable module?
Yes, it is possible to populate the DocType list based on login user role.
Code example for 'Administrator' role:
using PX.Data;
using PX.Objects.AP;
using PX.SM;
namespace PX.Objects.AP
{
public class APInvoiceEntry_Extension:PXGraphExtension<APInvoiceEntry>
{
public PXSelect<UsersInRoles,
Where<UsersInRoles.username, Equal<Current<AccessInfo.userName>>,
And<UsersInRoles.rolename, Equal<Required<UsersInRoles.rolename>>>>> isLoginUserInRole;
public void APInvoice_RowSelected(PXCache sender, PXRowSelectedEventArgs e)
{
if (isLoginUserInRole.Select("Administrator").Count > 0)
{
PXDefaultAttribute.SetDefault<APInvoice.docType>(sender, APDocType.Invoice);
PXStringListAttribute.SetList<APInvoice.docType>(sender,
null,
new string[] { APDocType.Invoice },
new string[] { Messages.Invoice });
}
}
}
}
When login user is in 'Administrator' role, only 'Bill' is shown in DocType:
Related
import { DragSource } from 'react-dnd'
import {ViewTypes, DATETIME_FORMAT} from './index'
import {DnDTypes} from './DnDTypes'
export default class DnDSource {
constructor(resolveDragObjFunc, DecoratedComponent, dndType = DnDTypes.EVENT) {
this.resolveDragObjFunc = resolveDragObjFunc;
this.DecoratedComponent = DecoratedComponent;
this.dndType = dndType;
this.dragSource = DragSource(this.dndType, this.getDragSpec(), this.getDragCollect)(this.DecoratedComponent);
}
getDragSpec = () => {
return {
beginDrag: (props, monitor, component) => {
return this.resolveDragObjFunc(props);
},
endDrag: (props, monitor, component) => {
if(!monitor.didDrop()) return;
const {moveEvent, newEvent, schedulerData } = props;
const {events, config, viewType, localeMoment} = schedulerData;
const item = monitor.getItem();
const type = monitor.getItemType();
const dropResult = monitor.getDropResult();
let slotId = dropResult.slotId, slotName = dropResult.slotName;
let newStart = dropResult.start, newEnd = dropResult.end;
let initialStart = dropResult.initialStart, initialEnd = dropResult.initialEnd;
let action = 'New';
let isEvent = type === DnDTypes.EVENT;
if(isEvent) {
const event = item;
if(config.relativeMove) {
newStart = localeMoment(event.start).add(localeMoment(newStart).diff(localeMoment(initialStart)), 'ms').format(DATETIME_FORMAT);
} else {
if(viewType !== ViewTypes.Day) {
let tmpMoment = localeMoment(newStart);
newStart = localeMoment(event.start).year(tmpMoment.year()).month(tmpMoment.month()).date(tmpMoment.date()).format(DATETIME_FORMAT);
}
}
newEnd = localeMoment(newStart).add(localeMoment(event.end).diff(localeMoment(event.start)), 'ms').format(DATETIME_FORMAT);
//if crossResourceMove disabled, slot returns old value
if(config.crossResourceMove === false) {
slotId = schedulerData._getEventSlotId(item);
slotName = undefined;
let slot = schedulerData.getSlotById(slotId);
if(!!slot)
slotName = slot.name;
}
action = 'Move';
}
let hasConflict = false;
if(config.checkConflict) {
let start = localeMoment(newStart),
end = localeMoment(newEnd);
events.forEach((e) =>{
if(schedulerData._getEventSlotId(e) === slotId && (!isEvent || e.id !== item.id)) {
let eStart = localeMoment(e.start),
eEnd = localeMoment(e.end);
if((start >= eStart && start < eEnd) || (end > eStart && end <= eEnd) || (eStart >= start && eStart < end) || (eEnd > start && eEnd <= end))
hasConflict = true;
}
});
}
if(hasConflict) {
const {conflictOccurred} = props;
if(conflictOccurred != undefined){
conflictOccurred(schedulerData, action, item, type, slotId, slotName, newStart, newEnd);
}
else {
console.log('Conflict occurred, set conflictOccurred func in Scheduler to handle it');
}
}
else {
if(isEvent) {
if (moveEvent !== undefined) {
moveEvent(schedulerData, item, slotId, slotName, newStart, newEnd);
}
}
else {
if(newEvent !== undefined)
newEvent(schedulerData, slotId, slotName, newStart, newEnd, type, item);
}
}
},
canDrag: (props) => {
const {schedulerData, resourceEvents} = props;
const item = this.resolveDragObjFunc(props);
if(schedulerData._isResizing()) return false;
const {config} = schedulerData;
return config.movable && (resourceEvents == undefined || !resourceEvents.groupOnly) && (item.movable == undefined || item.movable !== false);
}
}
}
getDragCollect = (connect, monitor) => {
return {
connectDragSource: connect.dragSource(),
isDragging: monitor.isDragging(),
connectDragPreview: connect.dragPreview()
};
}
getDragSource = () => {
return this.dragSource;
}
}
I am using Ant design in my project. For file upload, I am using Dragger from Ant Design.
The issue is, when i set multiple = false and maxCount = 1, i can drag multiple files. Though its randomly uploading 1 file only but in my scenerio as I am dragging multiple files I need to show an alert saying Multiple file upload is not allowed.
I tried setting a value in onDrop method which I wanted to use in beforeUpload method. But it seems, beforeUpload is getting called before onDrop. So its not possible this way.
I tried these but didn't work: https://github.com/ant-design/ant-design/issues/17397
Here is my code of the dragger
const [droppedFile, setDroppedFile] = useState(0);
const uploadData = {
name: 'file',
multiple: false,
maxCount: 1,
accept: 'text/csv,application/vnd.ms-excel',
action: BASEURL + '/campaign/csv',
data: {
campaign: props.id
},
headers: {
Authorization: "Bearer " + props.token
},
beforeUpload: file => {
console.log(file);
if (droppedFile > 1) {
message.warning(`Multiple files are not allowed. Only one CSV file will be uploaded at a time.`);
return false;
}
if (file.type != 'text/csv'
&& file.type != 'application/vnd.ms-excel') {
message.error(`Invalid file format. Please upload a CSV file.`);
return false;
}
return true;
},
onChange(info) {
const { status } = info.file;
if (status !== 'uploading') {
console.log('uploading',info);
}
if (status === 'done') {
// message.success(`${info.file.name} file uploaded successfully.`);
console.log("uploaded file", info);
if (info.file.response == 0) {
emptyData()
}
setData(info.file.response)
} else if (status === 'error'
|| (info.file.type != 'text/csv'
&& info.file.type != 'application/vnd.ms-excel')
) {
console.log(info);
// message.error(`${info.file.name} file upload failed.`);
if (info.file.response.message == 'Not Found Exception') {
message.error(`No valid LinkedIn profile found`);
} else {
message.error(`Invalid file format. Please upload a CSV file.`);
}
}
},
onDrop(e) {
console.log('Dropped files', e.dataTransfer.files);
// beforeUpload(e.dataTransfer.files)
setDroppedFile(e.dataTransfer.files.length)
if (e.dataTransfer.files.length > 1) {
let validFile = false;
for (let i = 0; i < e.dataTransfer.files.length; i++) {
if (e.dataTransfer.files[i].type == 'text/csv' || e.dataTransfer.files[i].type == 'application/vnd.ms-excel') {
validFile = true;
break;
}
}
if (!validFile) {
// message.error(`Invalid file format. Please upload a CSV file.`);
message.error(`Multiple files are not allowed. Upload only one file at a time.`);
// message.error(`${info.file.name} file upload failed.`);
} else {
message.warning(`Multiple files are not allowed. Only one CSV file will be uploaded at a time.`);
}
} else {
if (e.dataTransfer.files[0].type != 'text/csv' && e.dataTransfer.files[0].type != 'application/vnd.ms-excel') {
message.error(`Invalid file format. Please upload a CSV file.`);
}
}
},
};
And here is the html part
<Dragger {...uploadData}>
<p className="ant-upload-drag-icon">
<InboxOutlined />
</p>
<p className="ant-upload-text">Click or drag file to this area to upload</p>
<p className="ant-upload-hint">
Support for a single or bulk upload. Strictly prohibit from uploading company data or other
band files
</p>
</Dragger>
I'm trying to make a call to the large-bert model to do a summary task but the response is always the same generic "CNN.com will feature iReporter photos in a weekly Travel Snapshots gallery. Please submit your best shots of the U.S. for next week. Visit CNN.com/Travel next Wednesday for a new gallery of snapshots. Please share your best photos of the United States with CNN iReport." Which has nothing to do with my test input from wikipedia. I tried modeling my code off of "https://api-inference.huggingface.co/docs/node/html/detailed_parameters.html#summarization-task" which is more specific to nodeJS but I figured should be very similar.
I was wondering if there was an explanation. Am I missing some input or passing the data wrong?
The following is the attempted code
const response = await fetch(
"https://api-inference.huggingface.co/models/facebook/bart-large-cnn",
{
headers: { Authorization: `Bearer ${API_TOKEN}` },
method: "POST",
data: {
"inputs": JSON.stringify(script),
"parameters": {"do_sample": false},
},
}
);
const result = await response.json();
setSummation(JSON.stringify(result[0].summary_text))
const response = await fetch(
"https://api-inference.huggingface.co/models/facebook/bart-large-cnn",
{
headers: { Authorization: `Bearer ${API_TOKEN}` },
method: "POST",
body: JSON.stringify(script),
}
);
const result = await response.json();
It appears I wasn't passing the script data properly.
I am implementing the Search function using spotify api.
However, if you request get to api now, 400 will be returned.
I want you to help me with this.
axios({
headers: {
"Authorization": `Bearer ${token}`
},
method: 'GET',
url: 'https://api.spotify.com/v1/search',
qs: {
q: value,
type: 'album',
},
}).then((res) => {
console.log(res);
}).catch(err => {
console.log(err);
})
const options = {
method: 'GET',
url: `https://api.spotify.com/v1/search?q=${value}&type=album`,
headers: {
'Authorization': `Bearer ${token}`,
"Accept": "application/json",
"Content-Type": "application/json",
}
}
axios(options).then((res)=>console.log(res))
.catch(err=>console.error(err))
wikiApp.config(['$routeProvider','authService',
function($routeProvider,authService) {
var admin = authService.getLoggedin();
$routeProvider
.when('/hjem',{
templateUrl: 'partials/homeContent.html',
admin: false
})
.when('/articles/:article',{
templateUrl: 'partials/articles.html',
admin: false
})
.when('/newArticle',{
templateUrl: 'partials/postArticle.html',
controller: 'articleController',
admin: true
})
The authService.getLoggedin() returns either false or true depending on if the user is logged in or not. Then i would like to not allow them to the Url if they are not allowed.
But i get this error:
Error: [$injector:modulerr] Failed to instantiate module wikiApp due to:
[$injector:unpr] Unknown provider: authService
angular.config only accepts Providers
every service, factory etc are instances of Provider
So to inject a service in config you just need to call the Provider of the service by adding 'Provider' to it's name.
angular.module('myApp')
.service('FooService', function(){
//...etc
})
.config(function(FooServiceProvider){
//...etc
});
During the configuration phase you can only ask for providers ($routeProvider, $locationProvider etc.) it means you cannot inject any other instance, so I would suggest injecting your service in the run phase, there your will have an instance of your service.
// configuration
app.config(function($routeProvider) {
});
//inject any instance
app.run(function($rootScope,authService) {
var admin = authService.getLoggedin();
$rootScope.$on('$routeChangeStart', function(next, current) {
// your logic here...
});
});
If you want to call an external function (in your case Service function) form your routes (.config) as shown below: templateProvider.getTemplate('about')
.state('index.about', {
url: "/about",
templateUrl: templateProvider.getTemplate('about'),
controller: 'AboutCtrl',
controllerAs: 'about',
data: {pageTitle: 'About Us Page'}
})
you cannot create a Service or Factory for that. Instead you must create a Provider.
Here’s a real example of a Provider that generates the template path from the name:
(function () {
'use strict';
angular
.module('mega-app')
.provider('template', provider);
function provider(CONSTANT) {
// The provider must include a $get() method This $get() method
// will be invoked using $injector.invoke() and can therefore use
// dependency-injection.
this.$get = function () {
return {}
};
/**
* generates template path from it's name
*
* #param name
* #returns {string}
*/
this.getTemplate = function (name) {
return CONSTANT.TEMPLATES_URL + name + '/' + name + '.html';
}
/**
* generates component path from it's name
* #param name
* #returns {string}
*/
this.getComponent = function (name) {
return CONSTANT.COMPONENTS_URL + name + '.html';
}
};
})();
The usage of such Provider in the routes (.config) will be as follow:
(function () {
'use strict';
angular
.module('mega-app')
.config(routes);
function routes($stateProvider, $urlRouterProvider, templateProvider) {
$stateProvider
//----------------------------------------------------------------
// First State
//----------------------------------------------------------------
.state('index', {
abstract: true,
url: "/index",
templateUrl: templateProvider.getComponent('content'),
controller: 'IndexCtrl',
controllerAs: 'index',
})
//----------------------------------------------------------------
// State
//----------------------------------------------------------------
.state('index.home', {
url: "/home",
templateUrl: templateProvider.getTemplate('home'),
controller: 'HomeCtrl',
controllerAs: 'home',
data: {pageTitle: 'Home Page'}
})
//----------------------------------------------------------------
// State
//----------------------------------------------------------------
.state('index.about', {
url: "/about",
templateUrl: templateProvider.getTemplate('about'),
controller: 'AboutCtrl',
controllerAs: 'about',
data: {pageTitle: 'About Us Page'}
})
//----------------------------------------------------------------
// Default State
//----------------------------------------------------------------
$urlRouterProvider.otherwise('/index/home');
};
})();
VIP Note:
to inject the provider you must postfix it with xxxProvider (that name of the provider should not be postfixed, only on injection in the .config).