YouTrack Workflow: Prevent Deletion - javascript

I've created a very simple workflow task for a cloud based YouTrack instance. The idea is to prevent (stop workflow) deletion of issues (we'd prefer to keep all issues, even if they were submitted by mistake). The code is provided below.
var entities = require('#jetbrains/youtrack-scripting-api/entities');
var workflow = require('#jetbrains/youtrack-scripting-api/workflow');
exports.rule = entities.Issue.onChange({
// TODO: give the rule a human-readable title
title: 'When-issue-is-deleted',
guard: function(ctx) {
return ctx.issue.becomesRemoved;
},
action: function(ctx) {
workflow.check(false, 'Do not remove issues, please');
}
});
Though I believe it should work, when I tried to remove a new just created issue I received no error messages, and the issue was removed.

I'd recommend an easier way - just disable 'Delete issue' permission for the respective roles (https://www.jetbrains.com/help/youtrack/standalone/Create-and-Edit-Roles.html#editing_existing_roles) and users with these roles will not be able to delete issues.
As for becomesRemoved property which doesn't work properly - this is a known issue, please follow this ticket to receive further updates on it: https://youtrack.jetbrains.com/issue/JT-29303.

Just in case someone else stumbles upon this issue (quoting https://youtrack.jetbrains.com/issue/JT-55220)
To make your onChange rule triggered when an issue becomes removed, you'll need to specify the runOn attribute in the rule's declaration.
runOn: {
change: false,
removal: true
}

Related

Why do vuelidate validators no longer react to input changes?

I have a problem regarding form validation with vuelidate. I’m using Vue 2.9.6 with vuelidate 0.7.5
I recommend opening this jsfiddle while reading my problem description:
jsfiddle.net/Philgarth/h5v7km2s/
(SO prevents me from posting the link properly, sorry .... just prepend "https://")
I’m developing an account book for private bank accounts and currently I’m working on the depositor-form-component, where users can add new depositors. Each depositor must have a name and at least one bank account to submit the depositor-form and return to the account-view-component.
As you can see in the jsfiddle I have a textfield for the name and a dropdown for the accounts which initially is empty and disabled. A new account can be drafted by clicking the „+“-button besides the dropdown. With „drafted“ I mean, that the account in the finished app shouldn’t get posted to the database right away. Because users should be able to create multiple accounts for a depositor only the finished and validated depositor-object with one ore more accounts is sent to the database by submitting the whole depositor-form.
While a new account is drafted, the variable „pendingAccountCreation“ is set to true, which is why the account fields are displayed via „v-if“ as well as two buttons to submit or discard the account data.
When clicking on either of these buttons, the validation-object „updatedAccount“ should be resetted, so that by drafting another account the fields neither are dirty nor have errors.
Now the problem is, that the validators don’t react to changes to the input field in some cases – e.g. „required“ remains false although the input field is not empty.
I made some tests and could determine that the error only occurs, when an account-draft is discarded by clicking the „x“-button while no other accounts are already created. As soon as at least one account is created and available in the dropdown everything works as expected and the validators react to input changes when drafting another account.
Now if you want to help me I ask you to reproduce the error in the jsfiddle and try to figure out, what I’m doing wrong here.
Thanks in advance and have a nice day 😊
Change this code:
discardAccountDraft(accountValidator) {
accountValidator.$reset();
this.selectedAccountIndex = 0;
if (this.updatedDepositor.accounts.length !== 0) {
this.selectedAccount = this.updatedDepositor.accounts[0];
this.updatedAccount = this.cloneObject(this.selectedAccount);
} else {
this.updatedAccount = this.cloneObjectModel;
}
this.pendingAccountCreation = false;
},
to this code (jsfiddle):
discardAccountDraft(accountValidator) {
accountValidator.$reset();
this.selectedAccountIndex = 0;
if (this.updatedDepositor.accounts.length !== 0) {
this.selectedAccount = this.updatedDepositor.accounts[0];
this.updatedAccount = this.cloneObject(this.selectedAccount);
} else {
this.updatedAccount = this.cloneObjectModel({
id: "",
accountNumber: "",
iban: "",
bic: "",
accountDescription: "",
});
}
this.pendingAccountCreation = false;
},
I've just added empty model to your cloneObjectModel function, because it expects one... And this fixed the problem you mentioned:
error only occurs, when an account-draft is discarded by clicking the „x“-button while no other accounts are already created

Ag-grid: duplicate node id 107 detected from getRowNodeId callback , this could cause issues in your grid

I am going to do live data streaming on ag-grid datatable, so I used DeltaRowData for gridOptions and added getRowNodeId method as well which return unique value 'id'.
After all, I got a live update result on my grid table within some period I set, but some rows are duplicated so I can notice total count is a bit increased each time it loads updated data. The question title is warning message from browser console, I got bunch of these messages with different id number. Actually it is supposed not to do this from below docs. This is supposed to detect dups and smartly added new ones if not exist. Ofc, there are several ways to get refreshed data live, but I chose this one, since it says it helps to persist grid info like selected rows, current position of scroll on the grid etc. I am using vanilla js, not going to use any frameworks.
How do I make live data updated periodically without changing any current grid stuff? There is no error on the code, so do not try to speak about any bug. Maybe I am wrong with current implementation, Anyway, I want to know the idea or hear any implementation experience on this.
let gridOptions = {
....
deltaRowDataMode: true,
getRowNodeId = (data) => {
return data.id; // return the property you want set as the id.
}
}
fetch(loadUrl).then((res) => {
return res.json()
}).then((data) => {
gridOptions.api.setRowData(data);
})
...
If you get:
duplicated node warning
it means your getRowNodeId() has 1 value for 2 different rows.
here is part from source:
if (this.allNodesMap[node.id]) {
console.warn("ag-grid: duplicate node id '" + node.id + "' detected from getRowNodeId callback, this could cause issues in your grid.");
}
so try to check your data again.
if u 100% sure there is an error not related with your data - cut oof the private data, create a plinkr/stackblitz examples to reproduce your issue and then it would be simpler to check and help you.

Using FullCalendar, how to add information to EventObject when eventReceive?

I've started discovering and using FullCalendar but I'm stuck with it.
What I want to do is a ResourceTimeline in Month view, with external event dragging (a left panel).
The subject later would be to have a modal when you drop an event, in order to choose if you want the event to be from 8am to 12pm, or afternoon from 12pm to 6pm.
So first, I'd like to do a simple eventReceive without modal, to see if I can update the event when it's dropped.
But it seems I can't, what do I do wrong ?
From what I can understand, it looks like when you drop an event in month view, the event in the param sent to eventReceive is modified.
eventReceive(info) {
info.event.start = moment(info.event.start).add(8, 'hours').format('YYYY-MM-DD hh:mm:ss');
// var c = confirm('OK = morning, Cancel = aprem');
// if (c) {
// console.log("morning !")
// } else {
// console.log("afternoon !")
// }
}
Events are very basic because I wanted to complete them whenever I drop them into the calendar
new Draggable(listofEvents, {
itemSelector: '.draggable',
eventData(event) {
return {
title: event.innerText,
activite: event.dataset.activite,
allDayDefault: false,
}
},
})
I even tried to force allDayDefault to false but it doesn't change a thing...
Here is the codepen of the project in its current state : https://codepen.io/nurovek/pen/zYYWGyX?editors=1000
Sorry if my post lacks information, I'm not used to ask questions on SO. If it's lacking, I'll try to be more explicit if you ask me, of course !
As per the documentation, an event's public properties (such as "start", "end", title" etc) are read-only. Therefore to alter a property after the event is created you must run one of the "set" methods.
So your idea will work if you use the setDates method:
eventReceive(info) {
info.event.setDates(moment(info.event.start).add(8, 'hours').toDate(), info.event.end, { "allDay": false } )
console.log(info.event);
}
Demo: https://codepen.io/ADyson82/pen/dyymawy?editors=1000
P.S. You might notice I also made a few other little changes to your CodePen, mainly to correct all the links to CSS and JS files, since it was generating all sorts of console errors. These errors were because links were wrong or simply referred to something non-existent, and for some reason you were also using files from two different versions of fullCalendar (4.3.0 and 4.3.1), which is never a good idea if you want to ensure full compatibility.

Shopware 5, open BatchProcess window from Own Plugin

I hope its not to harsh to ask not to mince matters.
Here we go:
I have a problem developing a custom Plugin for Shopware 5.
I already have a working plugin which lists orders for certain criteria.
Now I want a Button (which i already have) in the toolbar of this grid-window.
The Button should open the Batch Process Window which is already available in the native "Order" Window of shopware.
Q: How Can I open this app with the selected Ids of my grid?
Heres what I have:
[...]
createToolbarButton: function () {
var me = this;
return Ext.create('Ext.button.Button', {
text: 'Batch Processing Orders',
name: 'customBatchProcessButton',
cls: 'secondary',
handler: function () {
me.onClickCustomBatchProcessButton(me);
}
});
},
onClickCustomBatchProcessButton: function(me){
var thisGrid = me.getTransferGrid();
var records = thisGrid.getSelectionModel().getSelection();
console.log("Grid");
console.log(thisGrid);
console.log("records");
console.log(records);
Shopware.app.Application.addSubApplication({
name: 'Shopware.apps.Order',
action: 'batch',
params: {
mode: 'multi',
records: records
}
});
}
[...]
It always opens the normal view of the order window. (no error in console)
Anybody has a suggestions?
That would be great!
Thanks for your time :)
Greetings
EDIT:
Hey, thank you for your reply so far.
I managed to open the Batch-process-window like this:
me.getView('Shopware.apps.Order.view.batch.Window').create({
orderStatusStore: Ext.create('Shopware.apps.Base.store.OrderStatus').load(),
records: orderRecords,
mode: 'multi'
}).show({});
But now the Problem ist, the Event for the Batch-Process isn't applied on the button on the form...
I am still on try and error.
Many Shopware ExtJS SubApplications can be executed from another app with certain parameters exactly the way you're trying to. Unfortunately I don't see any code in the Order plugin that might lead to the desired result. You can see what actions/params a Shopware SubApplication supports by reading the init function of the main controller -> Shopware.apps.Order.controller.Main
Shopware.apps.Customer.controller.Main from the Customer plugin for example accepts an action like you are using it – it is checking for this:
if (me.subApplication.action && me.subApplication.action.toLowerCase() === 'detail') {
if (me.subApplication.params && me.subApplication.params.customerId) {
//open the customer detail page with the passed customer id
...
In the Order plugin there is similar code, but it just takes an order ID and opens the detail page for the corresponding order. It apparently doesn't feature the batch.Window
You might be able to reuse this class somehow, but that might be a ton of code you need to adapt from the actual Order plugin. If you really need this feature, you can carefully read how the Order plugin is initializing the window and its dependencies and have a try.
I'd rather go for developing a lightweight module in this scenario (It's a frame within a backend window that just uses controllers and template views with PHP/Smarty/HTML)

Firebase array item is removed and immediately auto-added back (with AngularFire)

I am trying to remove an item from $firebaseArray (boxes).
The remove funcion:
function remove(boxJson) {
return boxes.$remove(boxJson);
}
It works, however it is immediately added back:
This is the method that brings the array:
function getBoxes(screenIndex) {
var boxesRef = screens
.child("s-" + screenIndex)
.child("boxes");
return $firebaseArray(boxesRef);
}
I thought perhaps I'm holding multiple references to the firebaseArray and when one deletes, the other adds, but then I thought firebase should handle it, no?
Anyway I'm lost on this, any idea?
UPDATE
When I hack it and delete twice (with a timeout) it seems to work:
function removeForce(screenIndex, boxId) {
setTimeout(function () {
API.removeBox(screenIndex, boxId);
}, 1000);
return API.removeBox(screenIndex, boxId);
}
and the API.removeBox:
function removeBox(screenIndex, boxId) {
var boxRef = screens
.child("s-" + screenIndex)
.child("boxes")
.child(boxId);
return boxRef.remove();
}
When you remove something from firebase it is asynchronous. Per the docs the proper way to remove an item is from firebase, using AngularFire is:
var obj = $firebaseObject(ref);
obj.$remove().then(function(ref) {
// data has been deleted locally and in the database
}, function(error) {
console.log("Error:", error);
});
$remove() ... Removes the entire object locally and from the database. This method returns a promise that will be fulfilled when the data has been removed from the server. The promise will be resolved with a Firebase reference for the exterminated record.
Link to docs: https://www.firebase.com/docs/web/libraries/angular/api.html#angularfire-firebaseobject-remove
The most likely cause is that you have a security rules that disallows the deletion.
When you call boxes.$remove Firebase immediately fires the child_removed event locally, to ensure the UI is updated quickly. It then sends the command to the Firebase servers to check it and update the database.
On the server there is a security rule that disallows this deletion. The servers send a "it failed" response back to the client, which then raises a child_added event to fix the UI.
Appearantly I was saving the items again after deleting them. Clearly my mistake:
function removeSelected(boxes) {
var selectedBoxes = Selector.getSelectedBoxes(boxes);
angular.forEach(selectedBoxes, function (box) {
BoxManager.remove(box);
});
Selector.clearSelection(boxes, true);
}
In the clearSelection method I was updating a field on the boxes and saved them again.
Besides the obvious mistake this is a lesson for me on how to work with Firebase. If some part of the system keeps a copy of your deleted item, saving it won't produce a bug but revive the deleted item.
For those, who have the similar issue, but didn't solve it yet.
There are two methods for listening events: .on() and .once(). In my case that was the cause of a problem.
I was working on a migration procedure, that should run once
writeRef
.orderByChild('text_hash')
.equalTo(addItem.text_hash)
.on('value', val => { // <--
if (!val.exists()) {
writeRef.push(addItem)
}
});
So the problem was exactly because of .on method. It fires each time after a data manipulation from FB's console.
Changing to .once solved that.

Categories