Alfresco Rule to Remove (unlink) Category from File - categories

In Alfresco users can use rules to link categories to files. There isn't an option to unlink categories from a file.
How do I programmatically remove (unlink) categories from a file without removing the classification aspect?
If a script is required, do you have an example?
I am using Alfresco 7.0 Share/Community version

take a look into the node browser:
Alfresco stores the categories on a node as an array of nodeRefs to the category nodes.
If you want to remove specific category from a node you need to save the array without the nodeRef for that category.
To illustrate that: the following example removes the category /Regions/EUROPE from a given document node:
var categories= document.properties["cm:categories"];
for (var i = 0; i < categories.length; i++) {
var categoryPath = categories[i].displayPath + '/' + categories[i].name;
logger.log(categoryPath);
if (categoryPath == '/categories/General/Regions/EUROPE'){
categories.splice(i, 1)
}
}
document.properties["cm:categories"]= categories;
document.save();

Related

Why when materials gets instanced, using renderer.sharedMaterial is the new instance but not the file?

I have a list of materials set by hand called LookUpMaterials and an object which I want to compare if it has those materials.
If both materials correlate, add them to a new list "ChangeableMaterials".
I'm comparing using the sharedMaterials so everything is fine at first. But, when adding the .material to this new list, it creates a instance of the material.
Note: Creating the instance using .material is intended since I'm gonna edit this material anyway.
List<Material> ChangeableMaterials = new List<Material>();
Renderer[] renderers = GetComponentsInChildren<Renderer>();
for(int i = 0; i < renderers.Length; i++)
{
for(int j = 0; j < renderers[i].sharedMaterials.Length; j++)
{
if(LookUpMaterials.Contains(renderers[i].sharedMaterials[j]))
{
ChangeableMaterials.Add(renderers[i].materials[j];
}
}
}
In the first comparison (i,j == 0,0), it runs ok and the material is added to the list. All materials turns into Instances. But then when using sharedMaterials also spits out materials (Instances) in place of the original files and the comparison fails.
I've read multiple times that .sharedMaterials should be the file and not the instance, this is not being the case!
Can someone help me? I can't find the mistake here, just plain confused..
Here's 3 lists how Debug.Log() spits the name of the material
LookUpMaterials
011_Pillow
.materials
011_Pillow (Instance)
.sharedMaterials
011_Pillow (Instance) - Shouldnt be only 011_Pillow?

Updating Embedded Charts in Google Docs with Google Apps Script

TLDR; How do I use the Script Editor in Docs to update an embedded Sheets chart in the document?
I know there is a script that does this for Google Slides, but I'm trying to do it in Google Docs and can't find any documentation thereof.
https://developers.google.com/slides/how-tos/add-chart#refreshing_a_chart
To be specific, I have a Google Doc. This doc contains about thirty tables and embedded charts that are all linked to a separate Google Sheet. All thirty come from a single Google Sheet. Now, I can have our non-geeky people click on all thirty "Update" hover buttons every time the spreadsheet changes, but I expect the spreadsheet to change a lot, and I would like to idiot-proof the document to ensure it's always up-to-date. As far as I can tell, this isn't a feature Google Apps does out of the box, so I wanted to write a script to do it.
But I can't find any way to access an EmbeddedChart from a Google Doc.
If I could run something like this like you can in Sheets, I could probably figure it out, but I can't:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var charts = sheet.getCharts();
for (var i in charts) {
var chart = charts[i];
// Update the chart
}
}
Although docs has the following function, DocumentApp.getActiveDocument(), an object Document doesn't contain a function getCharts(). I believe they're considered to be Images, but Images don't have an update function.
Is it even possible to access/update an EmbeddedChart in Docs using a script? Maybe by running the script through the spreadsheet on edit and updating the doc from there? Seems weird that you can do it in Slides of all things, but not Docs.
in Google Docs DOM charts as InlineImages here is the script that logs images attributes. but in they looks to be read only and documentation for this method ends with dead end: "null if the element contains multiple values for this attribute." https://developers.google.com/apps-script/reference/document/inline-image#getLinkUrl()
function myFunction() {
var doc = DocumentApp.getActiveDocument()
var body = doc.getBody()
var pars = body.getParagraphs()
var atts = img.getAttributes();
// Log the paragraph attributes.
for (var att in atts) {
Logger.log(att + ":" + atts[att]);
}
for (var par in pars) {
Logger.log(pars[par].getText());
var chN = pars[par].getNumChildren()
Logger.log(chN);
if(chN>0){
var type = pars[par].getChild(0).getType()
Logger.log(type);
if(type=="INLINE_IMAGE"){
var atts = pars[par].getChild(0).getAttributes()
Logger.log(JSON.stringify(atts));
for (var att in atts) {
Logger.log(att + ":" + atts[att]);
}
}
}
}
return
}
The goal is to update the ranges of each chart to encompass the number of columns and rows of the sheet referenced by the range.
The approach is to enumerate all ranges within all charts within all sheets, clear the range and re-add it with the right size. The getDataRange() function is a convenient way to get the right-sized range. The only tricky part is that you don't update the chart directly -- you need to get its builder, modify that, rebuild it, and then update the chart with the built object.
for (const sheet of SpreadsheetApp.getActive().getSheets()) {
for (const chart of sheet.getCharts()) {
const embeddedChartBuilder = chart.modify();
const ranges = chart.getRanges();
embeddedChartBuilder.clearRanges();
for (const range of ranges) {
const dataRange = range.getSheet().getDataRange();
embeddedChartBuilder.addRange(dataRange);
}
const embeddedChart = embeddedChartBuilder.build();
sheet.updateChart(embeddedChart);
}
}
The code sample assumes that your ranges are intended to encompass all the columns and rows of the referenced sheet.

Copy selection from Google Sheets into a Google Doc (using REST API?)

I have a Google Sheet whose contents I update with a python script that utilizes Google's REST API.
I want to copy a section of that Sheet into a given Google Doc automatically. (E.g. I want columns A:G of that sheet to appear in my Doc and get updated whenever the sheet does.) There are other elements (e.g. paragraphs) in the Doc, so it's important that the section appears in the location I specify each time (either by updating itself or by deleting the old section and inserting a new one).
Is that possible? How would I do it?
AFAIK, this is possible using Apps Script - Extending Google Docs and Extending Google Sheets.
You can create a Container-bound Scripts that have a onChange() trigger to get the updated value.
Write to Docs
//This can be openById() Open a document by ID.
var doc = DocumentApp.getActiveDocument();
var body = doc.getBody();
// Append a paragraph and a page break to the document body section directly.
body.appendParagraph("A paragraph.");
body.appendPageBreak();
Getting data from Sheets
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
// This represents ALL the data
var range = sheet.getDataRange();
var values = range.getValues();
// This logs the spreadsheet in CSV format with a trailing comma
for (var i = 0; i < values.length; i++) {
var row = "";
for (var j = 0; j < values[i].length; j++) {
if (values[i][j]) {
row = row + values[i][j];
}
row = row + ",";
}
Logger.log(row);
}
For implementation purposes, check the link. This shows how to create Google Docs and pass a value from Google Sheets using Apps Script.
Hope this helps.

Get a folder / zip with files in changelist(s) in TFS with complete directory structure

Our team uses TFS to manage workflow in the following flow:
work item -> source control -> changelist -> manual deploy to servers
Is there any way to just get a list of files with complete directory structure for a given changelist? Ideally, I'd like to be able to select multiple changelists and/or work items to get all the changelists associated with a work item, and get a complete directory structure for files in the changelists/work items.
Any suggestions would be appreciated, thanks!
You can probably use the following code snippit to get started
Uri tfsUri = new Uri(#"http://server:8080/tfs");
string serverPath = #"$/Project";
//Connect to the project collection
var projectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(
tfsUri, new UICredentialsProvider());
//Get the source code control service.
var sourceControl = projectCollection.GetService<VersionControlServer>();
var history = sourceControl.QueryHistory(
serverPath, //Source control path to the item. Like $/Project/Path ...
LatestVersionSpec.Instance, //Search latest version
0, //No unique deletion id.
RecursionType.Full, //Full recursion on the path
null, //All users
new ChangesetVersionSpec("9829"), //From the 7 days ago ...
LatestVersionSpec.Instance, //To the current version ...
Int32.MaxValue, //Include all changes. Can limit the number you get back.
true, //Include details of items, not just metadata.
false //Slot mode is false.
);
//Enumerate of the changesets.
foreach (Changeset changeset in history.OfType<Changeset>().Take(1))
{
foreach (var change in changeset.Changes)
{
change.Item.ServerItem.Dump();
}
}

How to assign two instances of the same plugins to different markers in a template

I need to insert two instances of tt_news on the same page and assign each instance of the plugin to a marker in the template. The two instances would be inserted in a backend column not rendered by my template, like border.
Since inserted plugins have a visible id on the backend, I was thinking about something like this
page.10.marks.NEWS1 < plugin.tt_news.idxxx
page.10.marks.NEWS2 < plugin.tt_news.idyyy
How can I achieve this ?
Hm... You could either insert content elements at the marker, like so
temp.contentElement = RECORDS
temp.contentElement {
tables = tt_content
dontCheckPid = 1 # if necessary
}
page.10.marks.NEWS1 < temp.contentElement
page.10.marks.NEWS1.source = UID_OF_NEWS_PLUGIN_ELEMENT
or, you could simply completely configure the plugin in ts
temp.news1 < plugin.tt_news
temp.news1 {
# configure
}
temp.news2 < plugin.tt_news
temp.news2 {
# configure
}
page.10.marks.NEWS1 < temp.news1
Hope that helps