How open new issue in YouTrack workflow script? - javascript

I am adding new script for YouTrack for adding new issue. And after adding new issue i need to show new issue for user for editing. And i don't know how it is possible. How is it do? Maybe should i get access to common methods? But i don't know how to do it.
My script
/**
* This is a template for an action rule. This rule defines a custom command
* and the changes that are applied by the command.
*
* For details, read the Quick Start Guide:
* https://www.jetbrains.com/help/youtrack/cloud/2022.2/Quick-Start-Guide-Workflows-JS.html
*/
const entities = require('#jetbrains/youtrack-scripting-api/entities');
exports.rule = entities.Issue.action({
// TODO: give the rule a human-readable title
title: 'Create_sub_task',
// TODO: define the custom command
command: 'create_sub_task',
guard: (ctx) => {
// TODO: define the condition that must be met to enable the custom command
return true;
},
action: (ctx) => {
var issue = ctx.issue;
var createIssue = function(name) {
var newIssue = new entities.Issue(ctx.currentUser, issue.project,
name + ' for ' + issue.summary);
//newIssue.fields.Subsystem = subsystem;
newIssue.fields.Type = "Detail";
newIssue.links['subtask of'].add(issue);
issue.links['parent for'].add(newIssue);
newIssue.fields.Author = entities.User.current;
// common.document.location.href = 'https://firstbiterp.youtrack.cloud/issue/FBITERP-2/IMBA';
return newIssue;
};
createIssue('NewTask');
},
requirements: {
// TODO: add requirements
}
});

This is currently not possible. The workflows run on the youtrack server, not in clients browser, and there is no support for passing such command back to client.
I believe the closest thing you can do is to show a notification with a link to the newly created issue. Look at clone as draft command, which does exactly that.

Related

How do I add javascript autocomplete to markdown mode of monaco editor?

I want to be able to use the javascript-autocomplete of the monaco editor inside of markdown documents as well, because markdown documents can contain code snippets of type javascript:
```javascript
window.blah
```
I know that I could register a custom CompletionItemProvider for markdown, but I want to use the javascript one already provided by monaco. I have not found a way to receive their provider however.
Javascript syntax highlighting already works in markdown code blocks.
My idea was to somehow get their provider using something like this:
(await monaco.languages.typescript.getJavaScriptWorker()).something
For that to work I'd have to register javascript on the editor however. Even if I do that, I don't seem to be able to find anything on their worker that could help me.
While there's a method to register a CompletionItemProvider (https://microsoft.github.io/monaco-editor/api/modules/monaco.languages.html#registercompletionitemprovider), I couldn't find any that could help me get a registered provider.
How can I use the javascript-autocomplete in markdown code blocks as well?
You are on the right track. Here's how I use typescript/javascript worker APIs to provide their completions in a mixed language environment:
return new Promise((resolve) => {
const workerPromise = (context.language === "javascript")
? languages.typescript.getJavaScriptWorker()
: languages.typescript.getTypeScriptWorker();
void workerPromise.then((worker: (...uris: Uri[]) => Promise<TypescriptWorker>) => {
void worker(model.uri).then((service) => {
const offset = model.getOffsetAt(localPosition);
const promise = service.getCompletionsAtPosition(model.uri.toString(), offset);
void promise.then((completions: CompletionInfo | undefined) => {
if (completions) {
const info = model.getWordUntilPosition(localPosition);
const replaceRange: IRange = {
startLineNumber: position.lineNumber,
startColumn: info.startColumn,
endLineNumber: position.lineNumber,
endColumn: info.endColumn,
};
resolve({
incomplete: false,
suggestions: completions.entries.map((entry) => ({
label: entry.name,
kind: this.convertKind(entry.kind),
range: replaceRange,
insertText: entry.insertText || entry.name,
} as CompletionItem)),
});
} else {
resolve({ incomplete: false, suggestions: [] });
}
});
});
});
});
Important here is that you create submodels with only the content of the parts in a single language (see Monaco.createModel()) and use that to invoke the completion items code.
In my app I split the content of an editor into blocks (each covering only full lines and which have a specific language attached to them). So they have a start line and an end line. With this information I can create sub models for each block:
/**
* #returns A local model which contains only the text of this block. The caller must dispose of it!
*/
public get model(): Monaco.ITextModel {
const editorModel = super.model; // Model for the entire editor content.
if (!this.internalModel || this.internalModel.isDisposed()) {
const localModel = Monaco.createModel("", this.language);
// Do other required preparations of the local model, if needed.
this.internalModel = localModel;
}
if (editorModel && this.modelNeedsUpdate) {
this.modelNeedsUpdate = false;
this.internalModel.setValue(editorModel.getValueInRange(
{
startLineNumber: this.startLine,
startColumn: 1,
endLineNumber: this.endLine,
endColumn: editorModel.getLineMaxColumn(this.endLine),
}, Monaco.EndOfLinePreference.LF),
);
}
return this.internalModel;
}

When showing a new growl in angularjs clear the old ones from view

I am working on growl.info() on angularjs and I have a question. How can I check if a growl exists in view (screen), when trying to add a new one? If a new one tries to be shown the previous one must be erased from screen. The code in controller is this:
$scope.showInfo= function () {
var info = "test";
growl.info(message.replace("{0}", info), {
ttl: 50000
});
};
but note that ttl is important too. If no new growl tries to be shown, the first must live for a long period. Thank you in advance!
Firslty we add a public variable:
$scope.growlMessge = null;
and then we check if it has already a value (just to destroy it), before giving the new one
$scope.showInfo= function () {
if ($scope.growlMessage != null) {
$scope.growlMessage.destroy();
}
var info = "test";
$scope.growlMessage = growl.info(message.replace("{0}", info), {
ttl: 50000
});
};

N/currentRecord module does not exist when uploading User Event script to NetSuite (SuiteScript 2.0)

I am trying to upload the below script to NetSuite in order to do a currency conversion from the purchase order currency to USD.
I would like a custom field to be updated with the USD amount whenever a user keys in any items into a purchase order.
When I upload the script, I receive the following error message:
Fail to evaluate script: {"type":"error.SuiteScriptModuleLoaderError","name":"MODULE_DOES_NOT_EXIST","message":"Module does not exist: N/currentRecord.js","stack":[]}**
Would greatly appreciate some guidance. Thank you.
/**
*#NApiVersion 2.x
*#NModuleScope Public
*#NScriptType UserEventScript
*/
define(['N/currency', 'N/currentRecord'],function(currency, currentRecord) {
function POCurrencyConversion() {
var Fixed_Currency = 'USD';
var Transaction_Currency = currentRecord.getValue('currency');
var Tx_currency_total = currentRecord.getValue('total');
var rate = currency.exchangeRate({
source: Transaction_Currency,
target: Fixed_Currency
});
var ConvertedAmount = Tx_currency_total * rate;
currentRecord.setValue('custbody_po_total_usd',ConvertedAmount)
}
POCurrencyConversion();
});
In User Events, you do not need the currentRecord module. Rather, you can retrieve the record in context from the parameter that NetSuite passes into your event handler function:
function beforeSubmit(context) {
var Transaction_Currency = context.newRecord.getValue({fieldId: "currency"});
var Tx_currency_total = context.newRecord.getValue({fieldId: "total"});
// etc
}
You cannot use "N/currentRecord" module in User Event Script.
This module is supported in Client Script.
instead you can make use of context.newRecord.

Sequelize: can you use hooks to add a comment to a query?

Heroku recently posted a list of some good tips for postgres. I was most intreged by the Track the Source of Your Queries section. I was curious if this was something that's possible to use with Sequelize. I know that sequelize has hooks, but wasn't sure if hooks could be used to make actual query string adjustments.
I'm curious if it's possible to use a hook or another Sequelize method to append a comment to Sequelize query (without using .raw) to keep track of where the query was called from.
(Appending and prepending to queries would also be helpful for implementing row-level security, specifically set role / reset role)
Edit: Would it be possible to use sequelize.fn() for this?
If you want to just insert a "tag" into the SQL query you could use Sequelize.literal() to pass a literal string to the query generator. Adding this to options.attributes.include will add it, however it will also need an alias so you would have to pass some kind of value as well.
Model.findById(id, {
attributes: {
include: [
[Sequelize.literal('/* your comment */ 1'), 'an_alias'],
],
},
});
This would produce SQL along the lines of
SELECT `model`.`id`, /* your comment */ 1 as `an_alias`
FROM `model` as `model`
WHERE `model`.`id` = ???
I played around with automating this a bit and it probably goes beyond the scope of this answer, but you could modify the Sequelize.Model.prototype before you create a connection using new Sequelize() to tweak the handling of the methods. You would need to do this for all the methods you want to "tag".
// alias findById() so we can call it once we fiddle with the input
Sequelize.Model.prototype.findById_untagged = Sequelize.Model.prototype.findById;
// override the findbyId() method so we can intercept the options.
Sequelize.Model.prototype.findById = function findById(id, options) {
// get the caller somehow (I was having trouble accessing the call stack properly)
const caller = ???;
// you need to make sure it's defined and you aren't overriding settings, etc
options.attributes.include.push([Sequelize.literal('/* your comment */ 1'), 'an_alias']);
// pass it off to the aliased method to continue as normal
return this.findById_untagged(id, options);
}
// create the connection
const connection = new Sequelize(...);
Note: it may not be possible to do this automagically as Sequelize has use strict so the arguments.caller and arguments.callee properties are not accessible.
2nd Note: if you don't care about modifying the Sequelize.Model prototypes you can also abstract your calls to the Sequelize methods and tweak the options there.
function Wrapper(model) {
return {
findById(id, options) {
// do your stuff
return model.findById(id, options);
},
};
}
Wrapper(Model).findById(id, options);
3rd Note: You can also submit a pull request to add this functionality to Sequelize under a new option value, like options.comment, which is added at the end of the query.
This overrides the sequelize.query() method that's internally used by Sequelize for all queries to add a comment showing the location of the query in the code. It also adds the stack trace to errors thrown.
const excludeLineTexts = ['node_modules', 'internal/process', ' anonymous ', 'runMicrotasks', 'Promise.'];
// overwrite the query() method that Sequelize uses internally for all queries so the error shows where in the code the query is from
sequelize.query = function () {
let stack;
const getStack = () => {
if (!stack) {
const o = {};
Error.captureStackTrace(o, sequelize.query);
stack = o.stack;
}
return stack;
};
const lines = getStack().split(/\n/g).slice(1);
const line = lines.find((l) => !excludeLineTexts.some((t) => l.includes(t)));
if (line) {
const methodAndPath = line.replace(/(\s+at (async )?|[^a-z0-9.:/\\\-_ ]|:\d+\)?$)/gi, '');
if (methodAndPath) {
const comment = `/* ${methodAndPath} */`;
if (arguments[0]?.query) {
arguments[0].query = `${comment} ${arguments[0].query}`;
} else {
arguments[0] = `${comment} ${arguments[0]}`;
}
}
}
return Sequelize.prototype.query.apply(this, arguments).catch((err) => {
err.fullStack = getStack();
throw err;
});
};

Meteor, Error: Can't wait without a fiber using Meteor.setTimeout() on the server

I'm fairly new to Meteor so I might be missing a key insight here.
Anyway, I want to indicate to users how many other users is on the site at the same time. I have an AuditItems collection already that stores kv-pairs for who, when and what that I can use for this type of computation. My Collections query is run with a new Date() parameter so I can't just observe the results, I have to rerun the query periodically.
I then made it reactive by calling changed on a Deps.Dependency.
Here is the code:
// publishing counts of the users that are logged on
// at the moment
Meteor.publish("user-activity", function () {
var self = this;
self.added("user-activity", "all-recent-activity", {'operations': getRecentActivityCountsCache});
self.ready();
Deps.autorun(function() {
self.changed("user-activity", "all-recent-activity", {'operations': getRecentActivityCounts()});
});
});
var getRecentActiveCountsDependency = new Deps.Dependency;
var getRecentActivityCountsCache = 0;
var getRecentActivityCounts = function() {
// register dependency with the caller
getRecentActiveCountsDependency.depend();
var now = new Date();
var aWhileAgo = new Date(now.valueOf() - (5 * 60 * 1000)); // 5 minutes
auditItems = AuditItems.find({'when': { '$gt': aWhileAgo }}).fetch();
console.log('raw data: ' + JSON.stringify(auditItems));
getRecentActivityCountsCache = _.chain(auditItems)
.groupBy('who')
.keys()
.size()
.value();
console.log('new count: ' + getRecentActivityCountsCache);
return getRecentActivityCountsCache;
};
Meteor.setTimeout(function() {
getRecentActiveCountsDependency.changed();
}, 60 * 1000); // 60 seconds
I am getting this error on the console the first time the timer fires:
Exception from Deps recompute: Error: Can't wait without a fiber
at Function.wait (/home/vagrant/.meteor/tools/3cba50c44a/lib/node_modules/fibers/future.js:83:9)
at Object.Future.wait (/home/vagrant/.meteor/tools/3cba50c44a/lib/node_modules/fibers/future.js:325:10)
at _.extend._nextObject (packages/mongo-livedata/mongo_driver.js:540)
at _.extend.forEach (packages/mongo-livedata/mongo_driver.js:570)
at _.extend.map (packages/mongo-livedata/mongo_driver.js:582)
at _.extend.fetch (packages/mongo-livedata/mongo_driver.js:606)
at _.each.Cursor.(anonymous function) [as fetch] (packages/mongo-livedata/mongo_driver.js:444)
at getRecentActivityCounts (app/server/server.js:26:70)
at null._func (app/server/server.js:12:79)
at _.extend._compute (packages/deps/deps.js:129)
All the Deps methods can only be used on the Client. The error you get is around the way Deps was built (since the client doesn't use fibers).
If you want to have reactivity on the server you need to use observe or observeChanges. Using the added and removed handle & you could query the date at that point (when the document changes).
You could also use Meteor.setInterval to periodically remove the older users from there.
One of the things you could do is use a package like meteor-prescence which does it all for you. What it does is it holds a live collection containing info on everyone who is online, then when they go offline/after a timeout it removes them from the collection using a periodic Meteor.setInterval method.

Categories