Access array index Yup conditional validation - yup

I want to use YUP conditional validation where the value of element answer[0] is used to see if the element ratio[0] is mandatory or not.
I am having trouble accessing the index [0] of answer to do that validation.
Any ideas? (I wrote answer.0 but it did not work).
explosion: Yup.object({
ratio: Yup.object({
0: Yup.number()
.typeError("value between 0 and 1")
.min(0, "Value between 0 and 1")
.max(1, "Value between 0 and 1")
Y.when("answer.0", {
is: "no",
then: (s) => s.notRequired(),
otherwise: (s) => s.required("Explosion probability"),
}),
}),
answer: Yup.object({
0: Yup.string().required("Mandatory field"),
}),
}),

Related

JOI validation when condition not working as expected

I have the following JOI schema defined;
schema = Joi.object({
flag: Joi.boolean()
.required(),
toolDetail: Joi.array().items(
Joi.object({
amount: Joi.number()
.min(0)
.max(499.99)
.precision(2)
.options({ convert: false })
.when('flag', {
is: true,
then: Joi.number().required(),
otherwise: Joi.number()
.strip()
.optional()
.allow(''),
}),
tool: Joi.string()
.min(0)
.max(500)
.when('flag', {
is: true,
then: Joi.string().required(),
otherwise: Joi.string()
.strip()
.optional()
.allow(''),
}),
}),
),
});
I have confirmed that the flag is being set correctly, but it seems that 'amount' and 'tool' is always hitting the otherwise condition, regardless of the value set in the 'flag'.
Is there something incorrect in my definition?
Works as expected once I added 4 dots prefix to the flag
.when('....flag', {
https://joi.dev/api/?v=17.2.1#relative-references

How to write message to Mattermost using Fastlane?

How do I write a message to Mattermost using Fastlane ?
Below is my trial. I got most from this link.
What is still wrong ?
(of course, I replaced the MATTERMOST_WEBHOOK_URL by the actual value that I established in Mattermost).
In the link above, I saw an actions folder with a mattermost.rb file
How do I get this action to work ? What do I need to do inside my Fastfile or anywhere in order to get this to work ?
In fact, running the fastlane send_message lane, I get a success. But unfortunately, nothing is visible in my Mattermost channel.
Inside my Fastfile, I do:
def send_message_to_mattermost(options)
unless ENV['MATTERMOST_WEBHOOK_URL'].nil? || ENV['MATTERMOST_WEBHOOK_URL'].empty?
mattermost(
pretext: options[:pretext],
message: options[:msg],
default_payloads: options[:default_payloads],
username: 'Fastlane',
icon_url: 'https://s3-eu-west-1.amazonaws.com/fastlane.tools/fastlane.png',
payload: {},
attachment_properties: {
title: options[:title],
thumb_url: options[:thumb_url],
fields: [{
title: 'Version',
value: options[:version_number],
short: true
},
{
title: 'Build Number',
value: options[:build_number],
short: true
},
{
title: 'Built by',
value: 'Jenkins',
short: true
}]
},
success: options[:success]
)
end
end
And my Fastlane lane looks like this:
lane :send_message do
send_message_to_mattermost({
:version_number => ENV['VERSION_NUMBER'],
:build_number => ENV["BUILD_NUMBER"],
:pretext => ENV['MAIN_APP_IDENTIFIER'],
:title => 'Unsuccessful Build',
:thumb_url => 'https://support.apple.com/library/content/dam/edam/applecare/images/en_US/iOS/move-to-ios-icon.png',
:msg => "My message...",
:default_payloads => [:lane],
:success => true
})
end
Is mattermost(...) a standard command in Fastlane ? If not what do I need to do in order to send information to a Mattermost channel from Fastlane ?
I finally found a solution.
What was missing is to set the ENV["MATTERMOST_WEBHOOK_URL"] upfront
before_all do
ENV["MATTERMOST_WEBHOOK_URL"] = 'https://my_new_webooh_from_mattermost'
end
...and leave the following code intact (i.e. do not replace 'MATTERMOST_WEBHOOK_URL' by anything else - the before_all does the trick...)
def send_message_to_mattermost(options)
unless ENV['MATTERMOST_WEBHOOK_URL'].nil? || ENV['MATTERMOST_WEBHOOK_URL'].empty?
mattermost(
pretext: options[:pretext],
message: options[:msg],
default_payloads: options[:default_payloads],
username: 'Fastlane',
icon_url: 'https://s3-eu-west-1.amazonaws.com/fastlane.tools/fastlane.png',
payload: {},
attachment_properties: {
title: options[:title],
thumb_url: options[:thumb_url],
fields: [{
title: 'Version',
value: options[:version_number],
short: true
},
{
title: 'Build Number',
value: options[:build_number],
short: true
},
{
title: 'Built by',
value: 'Jenkins',
short: true
}]
},
success: options[:success]
)
end
end

Issue Populating Filter Value for AG Grid agSetColumnFilter

I'm trying to populate the value for the agSetColumnFilter, but I'm getting an error that I cannot find anything where in documentation (or anywhere online). Has anyone ever run into this issue?
This is what the column definition looks like:
columnDefs.push({
headerName: col.name,
field: col.name,
def: col,
rowGroup: k < groupedColumnCount ? true : false,
pinned: k < _this.groupBy.length ? 'left' : null,
lockPinned: k < _this.groupBy.length ? true : false,
hide: k < groupedColumnCount ? true : false,
suppressToolPanel: _this.groupBy.length ? true : false,
valueGetter: function(data){
if(data.data){
var def = data.colDef.def;
var value = data.data[data.colDef.field];
if(value){
return value.value;
}else{
return null;
}
}else{
return data.value;
}
},
valueFormatter: function(data){
if(data.data){
var def = data.colDef.def;
var value = data.data[data.colDef.field];
if(!value) return null;
if(value.formatted){
_this.cache[data.colDef.field + value.value] = value.formatted;
}
return value.formatted ? value.formatted : value.value;
}else{
if(_this.cache[data.colDef.field + data.value]){
return _this.cache[data.colDef.field + data.value];
}else{
return data.value;
}
}
},
keyCreator: function(params){
console.log(params);
},
filter: 'agSetColumnFilter',
filterParams: {
values: function (params) {
params.success([{
$uri: 'nhuihi',
value: {
$value: 'some text'
}
}]);
}
}
});
I'm only printing out keyCreator params for now since I don't know what will actually be available in the data. The idea is that I can set values using complex objects returned from the server and display a formatted value instead of a key. This is the error I'm getting.
ag-grid-enterprise.min.noStyle.js:formatted:27684 Uncaught TypeError: Cannot read property 'onFilterValuesReady' of undefined
at t.setFilterValues (ag-grid-enterprise.min.noStyle.js:formatted:27684)
at e.modelUpdatedFunc (ag-grid-enterprise.min.noStyle.js:formatted:27609)
at e.onAsyncValuesLoaded (ag-grid-enterprise.min.noStyle.js:formatted:27917)
at values (comparison-table-v7.js:1253)
at e.createAllUniqueValues (ag-grid-enterprise.min.noStyle.js:formatted:27909)
at new e (ag-grid-enterprise.min.noStyle.js:formatted:27867)
at t.initialiseFilterBodyUi (ag-grid-enterprise.min.noStyle.js:formatted:27608)
at t.init (ag-grid-enterprise.min.noStyle.js:formatted:18945)
at e.initialiseComponent (ag-grid-enterprise.min.noStyle.js:formatted:10602)
at e.createAgGridComponent (ag-grid-enterprise.min.noStyle.js:formatted:10574)
Here's a test case for it as well. I simply modified the example by AG Grid. https://plnkr.co/edit/GURQHP0KKFpJ9kwaU83M?p=preview
If you open up console, you will see an error when you click on Athletes filter.
Also reported on GitHub: https://github.com/ag-grid/ag-grid/issues/2829
If you need to configure filter values without async requests
filterParams: {
values: getFilterValuesData()
}
getFilterValuesData(){
//data preparation
//little bit modified sample to present that you can handle your logic here
let data = [];
[
'John Joe Nevin',
'Katie Taylor',
'Paddy Barnes',
'Kenny Egan',
'Darren Sutherland',
'Margaret Thatcher',
'Tony Blair',
'Ronald Regan',
'Barack Obama'
].forEach(i=>{
data.push(i);
});
return data;
}
If it requires to make an async request for data preparation you can use callback function:
filterParams: {
values: (params)=>{
setTimeout(()=>{ -- setTimeout on this case only for async request imitation
params.success(['value 1', 'value 2'])
}, 5000)
}
}
Notice: params.success(...) should be used only with an async request
Doc: ag-grid Asynchronous Values

Joi validate presence of a key or another one

I'm using Joi for http body validation. I want to allow keyA to be present OR a keyB to be present and required but not both. I don't find in documentation what I'm looking for and it seems that a cycling loop appear in my schema.
const messageSchema = Joi.object().keys({
keyA: Joi.when('keyB', { is: Joi.exist(), then: Joi.forbidden(), otherwise: Joi.string().required() }),
keyB: Joi.when('keyA', { is: Joi.exist(), then: Joi.forbidden(), otherwise: Joi.string().uri().required() }),
});
Any idea ?
Finally found what I was looking for :
const messageSchema = Joi.object().keys({
keyA: Joi.string(),
keyB: Joi.string().uri(),
}).or('keyA', 'keyB');

React JS: Component not updating, after calling setState

I've got a small react app I'm playing with, just go get the hang of the library. The app is just a series of lists, which are populated from a server. When a list item is clicked, the value of that item is added to a list filters at the app level, which will then be used to call new data to populate the lists.
The problem is that I can't seem to get my lists to reconcile with the new data from the app (parent), even when calling setState. Here's my code (coffee):
###
#jsx React.DOM
###
{div, h1, h2, h4, ul, li, form, input, br, p, strong, span, a} = React.DOM
SearchApp = React.createClass
handleTopItemClick: (filter) ->
facet = filter.field
filters = #state.filters
if filters.facets[facet] and filters.facets[facet].length > 0
filters.facets[facet].push filter.value
else
filters.facets[facet] = [filter.value]
strArr = []
_.each filters.facets, (valArr, field) ->
_.each valArr, (val) ->
strArr.push "+(#{field}:\"#{val}\")"
#setState
filters: filters
queryStr: strArr.join(' ').trim()
getInitialState: ->
filters:
facets: {}
queryStr: ''
render: ->
(div {
id: 'content'
className: "search-wrap"
},
(h1 {}, "Search")
(div
id: 'widgets',
(TopList
title: 'Top Domains'
params:
query: #state.queryStr
field: 'domain'
onItemClick: #handleTopItemClick
)
(TopList
title: 'Top Senders'
params:
query: #state.queryStr
field: 'from'
onItemClick: #handleTopItemClick
)
(TopList
title: 'Top Recipient'
params:
query: #state.queryStr
field: 'recipient'
onItemClick: #handleTopItemClick
)
)
)
TopItem = React.createClass
getDefaultProps: ->
value: ''
count: 0
field: null
render: ->
(li {},
(a {
onClick: #handleClick
className: 'top-item-filter'
title: #props.value
},
(strong {}, #props.value)
(span {}, #props.count)
)
)
handleClick: (event) ->
event.preventDefault()
#props.onItemClick #props.value
TopList = React.createClass
getInitialState: ->
data: []
params: #props.params
componentWillReceiveProps: (nextProps) ->
#setState params: nextProps.params
componentWillMount: ->
request.post("/facet").send(#state.params).end (results) =>
#setState data: JSON.parse(results.text)
render: ->
itemNodes = _.map #state.data, (item) =>
key = item.value
TopItem
value: item.value
count: item.count
key: key
onItemClick: #handleItemClick
(div {className: 'widget top-item'},
(h2 {className: 'widget-header'}, "#{#props.title}")
(ul {className: 'top-items-list'}, itemNodes)
)
handleItemClick: (value) ->
#props.onItemClick
value: value
field: #props.params.field
React.renderComponent SearchApp(null), document.getElementById("content")
The lists all render fine the first time around, fetching the unfiltered data as expected. When I click on a list item, the SearchApp receives the event, and updates its own state accordingly. componentWillReceiveProps is properly called on the TopList classes, but the setState call there doesn't update their state, and thus, they aren't reconciling. I've verified that nextProps contains the new information. What am I missing?
There isn't really any reason to save the props in state; and it's much less error prone to keep props as the source of truth. It also simplifies the code a bit.
For the actual issue, though; componentWillMount is only called once here. If you want to repeat the AJAX request when new params are passed; you can do that like so:
TopList = React.createClass
getInitialState: ->
data: []
getSearchResultsFromServer: (params) ->
request.post("/facet").send(params).end (results) =>
if #isMounted()
#setState data: JSON.parse(results.text)
componentWillReceiveProps: (nextProps) -> #getSearchResultsFromServer nextProps.params
componentDidMount: -> #getSearchResultsFromServer #props.params
render: ->
itemNodes = _.map #state.data, (item) =>
key = item.value
TopItem
value: item.value
count: item.count
key: key
onItemClick: #handleItemClick
(div {className: 'widget top-item'},
(h2 {className: 'widget-header'}, "#{#props.title}")
(ul {className: 'top-items-list'}, itemNodes)
)
handleItemClick: (value) ->
#props.onItemClick
value: value
field: #props.params.field
Ideally, your ajax library would support aborting requests; and in componentWillUnmount you abort those requests.