Migrate serializer to typescript

This commit is contained in:
Paulo Gustavo Veiga 2022-01-03 08:27:00 -08:00
parent 954ee444ca
commit d91d6a2472
13 changed files with 97 additions and 96 deletions

View File

@ -24,15 +24,10 @@ class LinkModel extends FeatureModel {
this.setUrl(attributes.url);
}
/** @return {String} the url attribute value */
getUrl():string {
return this.getAttribute('url');
}
/**
* @param {String} url a URL provided by the user to set the link to
* @throws will throw an error if url is null or undefined
*/
setUrl(url: string): void {
$assert(url, 'url can not be null');

View File

@ -167,7 +167,6 @@ class NodeModel extends INodeModel {
append(child: NodeModel) {
$assert(child && child.isNodeModel(), 'Only NodeModel can be appended to Mindmap object');
this._children.push(child);
// eslint-disable-next-line no-param-reassign
child._parent = this;
}
@ -178,7 +177,6 @@ class NodeModel extends INodeModel {
removeChild(child: NodeModel): void {
$assert(child && child.isNodeModel(), 'Only NodeModel can be appended to Mindmap object.');
this._children = this._children.filter((c) => c !== child);
// eslint-disable-next-line no-param-reassign
child._parent = null;
}

View File

@ -26,12 +26,12 @@ class NoteModel extends FeatureModel {
}
/** */
getText() {
getText():string {
return this.getAttribute('text');
}
/** */
setText(text) {
setText(text:string) {
$assert(text, 'text can not be null');
this.setAttribute('text', text);
}

View File

@ -46,69 +46,56 @@ class RelationshipModel {
this._startArrow = false;
}
/** */
getFromNode() {
getFromNode(): number {
return this._sourceTargetId;
}
/** */
getToNode() {
getToNode(): number {
return this._targetTopicId;
}
/** */
getId():number {
getId(): number {
$assert(this._id, 'id is null');
return this._id;
}
/** */
getLineType() {
return this._lineType;
}
/** */
setLineType(lineType: number) {
this._lineType = lineType;
}
/** */
getSrcCtrlPoint(): Point {
return this._srcCtrlPoint;
}
/** */
setSrcCtrlPoint(srcCtrlPoint: Point) {
this._srcCtrlPoint = srcCtrlPoint;
}
/** */
getDestCtrlPoint(): Point {
return this._destCtrlPoint;
}
/** */
setDestCtrlPoint(destCtrlPoint: Point) {
setDestCtrlPoint(destCtrlPoint: Point): void {
this._destCtrlPoint = destCtrlPoint;
}
/** */
getEndArrow() {
getEndArrow(): boolean {
return this._endArrow;
}
/** */
setEndArrow(endArrow: boolean) {
this._endArrow = endArrow;
}
/** */
getStartArrow() {
getStartArrow(): boolean {
return this._startArrow;
}
/** */
setStartArrow(startArrow: boolean) {
setStartArrow(startArrow: boolean): void {
this._startArrow = startArrow;
}

View File

@ -16,20 +16,25 @@
* limitations under the License.
*/
import { $assert, $defined } from '@wisemapping/core-js';
import { Mindmap } from '../..';
import NodeModel from '../model/NodeModel';
import ModelCodeName from './ModelCodeName';
import XMLSerializer from './XMLSerializerPela';
import XMLMindmapSerializer from './XMLMindmapSerializer';
import XMLSerializerPela from './XMLSerializerPela';
class Beta2PelaMigrator {
constructor(betaSerializer) {
class Beta2PelaMigrator implements XMLMindmapSerializer {
private _betaSerializer: XMLMindmapSerializer;
private _pelaSerializer: XMLSerializerPela;
constructor(betaSerializer: XMLSerializerPela) {
this._betaSerializer = betaSerializer;
this._pelaSerializer = new XMLSerializer();
this._pelaSerializer = new XMLSerializerPela();
}
toXML(mindmap) {
toXML(mindmap: Mindmap) {
return this._pelaSerializer.toXML(mindmap);
}
loadFromDom(dom, mapId) {
loadFromDom(dom: Document, mapId: string): Mindmap {
$assert($defined(mapId), 'mapId can not be null');
const mindmap = this._betaSerializer.loadFromDom(dom, mapId);
mindmap.setVersion(ModelCodeName.PELA);
@ -44,13 +49,13 @@ class Beta2PelaMigrator {
return mindmap;
}
_fixPosition(parentModel) {
private _fixPosition(parentModel: NodeModel) {
const parentPos = parentModel.getPosition();
const isRight = parentPos.x > 0;
const me = this;
parentModel.getChildren().forEach((child) => {
if (!child.getPosition()) {
child.setPosition(parentPos.x + (50 * isRight ? 1 : -1), parentPos.y);
child.setPosition(parentPos.x + (isRight ? 1 : -1), parentPos.y);
}
me._fixPosition(child);
});

View File

@ -16,10 +16,6 @@
* limitations under the License.
*/
/**
* Enum for wisemap version names
* @enum {String}
*/
const ModelCodeName = {
BETA: 'beta',
PELA: 'pela',

View File

@ -18,18 +18,23 @@
import { $assert, $defined } from '@wisemapping/core-js';
import XMLSerializer from './XMLSerializerTango';
import ModelCodeName from './ModelCodeName';
import XMLMindmapSerializer from './XMLMindmapSerializer';
import Mindmap from '../model/Mindmap';
import NodeModel from '../model/NodeModel';
class Pela2TangoMigrator {
constructor(pelaSerializer) {
class Pela2TangoMigrator implements XMLMindmapSerializer {
private _pelaSerializer: XMLMindmapSerializer;
private _tangoSerializer: XMLSerializer;
constructor(pelaSerializer: XMLMindmapSerializer) {
this._pelaSerializer = pelaSerializer;
this._tangoSerializer = new XMLSerializer();
}
toXML(mindmap) {
toXML(mindmap: Mindmap): Document {
return this._tangoSerializer.toXML(mindmap);
}
loadFromDom(dom, mapId) {
loadFromDom(dom: Document, mapId: string): Mindmap {
$assert($defined(mapId), 'mapId can not be null');
const mindmap = this._pelaSerializer.loadFromDom(dom, mapId);
mindmap.setVersion(ModelCodeName.TANGO);
@ -38,23 +43,23 @@ class Pela2TangoMigrator {
return mindmap;
}
_fixOrder(mindmap) {
private _fixOrder(mindmap: Mindmap) {
// First level node policies has been changed.
const centralNode = mindmap.getBranches()[0];
const children = centralNode.getChildren();
const leftNodes = [];
const rightNodes = [];
for (let i = 0; i < children.length; i++) {
const child = children[i];
const centralNode: NodeModel = mindmap.getBranches()[0];
const children: NodeModel[] = centralNode.getChildren();
const leftNodes: NodeModel[] = [];
const rightNodes: NodeModel[] = [];
children.forEach((child) => {
const position = child.getPosition();
if (position.x < 0) {
leftNodes.push(child);
} else {
rightNodes.push(child);
}
}
rightNodes.sort((a, b) => a.getOrder() > b.getOrder());
leftNodes.sort((a, b) => a.getOrder() > b.getOrder());
rightNodes.sort((a, b) => a.getOrder() - b.getOrder());
leftNodes.sort((a, b) => a.getOrder() - b.getOrder());
});
for (let i = 0; i < rightNodes.length; i++) {
rightNodes[i].setOrder(i * 2);
@ -65,7 +70,7 @@ class Pela2TangoMigrator {
}
}
_fixPosition(mindmap) {
private _fixPosition(mindmap: Mindmap) {
// Position was not required in previous versions. Try to synthesize one .
const centralNode = mindmap.getBranches()[0];
const children = centralNode.getChildren();
@ -76,7 +81,7 @@ class Pela2TangoMigrator {
}
}
_fixNodePosition(node, parentPosition) {
_fixNodePosition(node: { getPosition: () => any; setPosition: (arg0: any, arg1: any) => void; getChildren: () => any; }, parentPosition: { x: number; y: any; }) {
// Position was not required in previous versions. Try to synthesize one .
let position = node.getPosition();
if (!position) {

View File

@ -0,0 +1,26 @@
/*
* Copyright [2021] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import Mindmap from "../model/Mindmap";
interface XMLMindmapSerializer {
toXML(mindmap: Mindmap): Document;
loadFromDom(dom: Document, mapId: string): Mindmap;
}
export default XMLMindmapSerializer;

View File

@ -21,9 +21,10 @@ import ModelCodeName from './ModelCodeName';
import Mindmap from '../model/Mindmap';
import FeatureModelFactory from '../model/FeatureModelFactory';
import NodeModel from '../model/NodeModel';
import XMLMindmapSerializer from './XMLMindmapSerializer';
class XMLSerializerBeta {
private static MAP_ROOT_NODE = 'map';
class XMLSerializerBeta implements XMLMindmapSerializer {
private static MAP_ROOT_NODE = 'map';
toXML(mindmap: Mindmap) {
$assert(mindmap, 'Can not save a null mindmap');
@ -119,27 +120,27 @@ class XMLSerializerBeta {
// ICONS
const icons = topic.findFeatureByType('icons');
icons.forEach((icon)=>{
icons.forEach((icon) => {
const iconDom = this._iconToXML(document, icon);
parentTopic.append(iconDom);
});
// LINKS
const links = topic.findFeatureByType('links');
icons.forEach((link)=>{
icons.forEach((link) => {
const linkDom = this._linkToXML(document, link);
parentTopic.append(linkDom);
});
const notes = topic.findFeatureByType('note');
notes.forEach((note)=>{
notes.forEach((note) => {
const noteDom = this._noteToXML(document, note);
parentTopic.append(noteDom);
});
// CHILDREN TOPICS
const childTopics = topic.getChildren();
childTopics.forEach((childTopic)=>{
childTopics.forEach((childTopic) => {
const childDom = this._topicToXML(document, childTopic);
parentTopic.append(childDom);
});

View File

@ -22,6 +22,8 @@ import Pela2TangoMigrator from './Pela2TangoMigrator';
import XMLSerializerBeta from './XMLSerializerBeta';
import XMLSerializerPela from './XMLSerializerPela';
import XMLSerializerTango from './XMLSerializerTango';
import { Mindmap } from '../..';
import XMLMindmapSerializer from './XMLMindmapSerializer';
const codeToSerializer = [
{
@ -48,7 +50,7 @@ class XMLSerializerFactory {
* @return {mindplot.persistence.XMLSerializer_Beta|mindplot.persistence.XMLSerializer_Pela|
* mindplot.persistence.XMLSerializer_Tango} serializer corresponding to the mindmap's version
*/
static createInstanceFromMindmap(mindmap) {
static createInstanceFromMindmap(mindmap: Mindmap) {
return XMLSerializerFactory
.getSerializer(mindmap.getVersion());
}
@ -57,7 +59,7 @@ class XMLSerializerFactory {
* @param domDocument
* @return serializer corresponding to the mindmap's version
*/
static createInstanceFromDocument(domDocument) {
static createInstanceFromDocument(domDocument: Document) {
const rootElem = domDocument.documentElement;
// Legacy version don't have version defined.
@ -74,7 +76,7 @@ class XMLSerializerFactory {
* @param {String} version the version name
* @return serializer
*/
static getSerializer(version = ModelCodeName.TANGO) {
static getSerializer(version = ModelCodeName.TANGO): XMLMindmapSerializer {
let found = false;
let result = null;
for (let i = 0; i < codeToSerializer.length; i++) {
@ -84,6 +86,7 @@ class XMLSerializerFactory {
if (found) result = new (codeToSerializer[i].serializer)();
} else {
const { migrator: Migrator } = codeToSerializer[i];
// @ts-ignore
result = new Migrator(result);
}
}

View File

@ -23,12 +23,14 @@ import ConnectionLine from '../ConnectionLine';
import FeatureModelFactory from '../model/FeatureModelFactory';
import NodeModel from '../model/NodeModel';
import { FeatureType } from '../model/FeatureModel';
import RelationshipModel from '../model/RelationshipModel';
import XMLMindmapSerializer from './XMLMindmapSerializer';
class XMLSerializerPela {
class XMLSerializerPela implements XMLMindmapSerializer {
private static MAP_ROOT_NODE = 'map';
private _idsMap: {};
toXML(mindmap: Mindmap) {
toXML(mindmap: Mindmap): Document {
$assert(mindmap, 'Can not save a null mindmap');
const document = createDocument();
@ -183,7 +185,7 @@ class XMLSerializerPela {
return parentTopic;
}
_noteTextToXML(document, elem, text) {
_noteTextToXML(document: Document, elem: Element, text: string) {
if (text.indexOf('\n') === -1) {
elem.setAttribute('text', this.rmXmlInv(text));
} else {
@ -194,13 +196,13 @@ class XMLSerializerPela {
}
}
static _relationshipToXML(document, relationship) {
static _relationshipToXML(document: Document, relationship: RelationshipModel) {
const result = document.createElement('relationship');
result.setAttribute('srcTopicId', relationship.getFromNode());
result.setAttribute('destTopicId', relationship.getToNode());
result.setAttribute('srcTopicId', relationship.getFromNode().toString());
result.setAttribute('destTopicId', relationship.getToNode().toString());
const lineType = relationship.getLineType();
result.setAttribute('lineType', lineType);
result.setAttribute('lineType', lineType.toString());
if (lineType === ConnectionLine.CURVED || lineType === ConnectionLine.SIMPLE_CURVED) {
if ($defined(relationship.getSrcCtrlPoint())) {
const srcPoint = relationship.getSrcCtrlPoint();
@ -217,8 +219,8 @@ class XMLSerializerPela {
);
}
}
result.setAttribute('endArrow', relationship.getEndArrow());
result.setAttribute('startArrow', relationship.getStartArrow());
result.setAttribute('endArrow', String(relationship.getEndArrow()));
result.setAttribute('startArrow', String(relationship.getStartArrow()));
return result;
}
@ -230,7 +232,7 @@ class XMLSerializerPela {
* @throws will throw an error if the document element is not consistent with a wisemap's root
* element
*/
loadFromDom(dom, mapId) {
loadFromDom(dom: Document, mapId: string) {
$assert(dom, 'dom can not be null');
$assert(mapId, 'mapId can not be null');

View File

@ -1,17 +0,0 @@
import beta2PelaMigrator from './Beta2PelaMigrator';
import modelCodeName from './ModelCodeName';
import pela2TangoMigrator from './Pela2TangoMigrator';
import xmlSerializerBeta from './XMLSerializerBeta';
import xmlSerializerPela from './XMLSerializerPela';
import xmlSerializerTango from './XMLSerializerTango';
import xmlSerializerFactory from './XMLSerializerFactory';
export default {
Beta2PelaMigrator: beta2PelaMigrator,
ModelCodeName: modelCodeName,
Pela2TangoMigrator: pela2TangoMigrator,
XMLSerializer_Beta: xmlSerializerBeta,
XMLSerializer_Pela: xmlSerializerPela,
XMLSerializer_Tango: xmlSerializerTango,
XMLSerializerFactory: xmlSerializerFactory,
};

View File

@ -1,5 +1,5 @@
<map name="complex" version="tango"><topic central="true" text="PPM Plan" id="1" bgColor="#32e36a"><topic position="241,250" order="0" text="Business Development " id="4" fontStyle=";;;bold;;"/><topic position="226,-100" order="2" text="Backlog Management" shape="line" id="18" fontStyle=";;;bold;;"><link url="https://docs.google.com/a/freeform.ca/drawings/d/1mrtkVAN3_XefJJCgfxw4Va6xk9TVDBKXDt_uzyIF4Us/edit" urlType="url"/></topic><topic position="-193,50" order="1" text="Freeform IT" id="10" fontStyle=";;;bold;;"/><topic position="-271,-50" order="3" text="Client Project Management" id="204" fontStyle=";;;bold;;"/><topic position="-183,-150" order="5" text="Governance &amp; Executive" id="206" fontStyle=";;;bold;;"/><topic position="124,-200" order="4" text="Finance" id="5" fontStyle=";;;bold;;"/><topic position="176,-150" order="6" text="Administration" id="3" fontStyle=";;;bold;;"/><topic position="222,100" order="8" text="Human Resources" id="154" fontStyle=";;;bold;;"><note><![CDATA[HR Vision: Freeform Solutions is successful at its mission, sustainable as an organization AND is a great place to work.
HR Mission: To provide a positive HR service experience for applicants and employees, and collaborate with departments to recruit, develop, support, and retain diverse and talented employees who are the key to Freeforms reputation and success.]]></note></topic><topic position="-202,150" order="7" text="Freeform Hosting" id="16" fontStyle=";;;bold;;"/><topic position="197,50" order="10" text="Community Outreach" id="247" fontStyle=";;;bold;;"/><topic position="124,300" order="12" text="R&amp;D" id="261" fontStyle=";;;bold;;"><topic position="230,289" order="0" text="Goals" id="263"/><topic position="239,313" order="1" text="Formulize" id="264"/></topic><topic position="-158,0" order="9" text="Probono" id="268"><topic position="-273,1" order="0" id="269"/></topic></topic><topic position="1558,-249" text="Strategy 2: Talent Development" id="31"><note><![CDATA[Strategy #2: Support the talent development of our employees through professional development and learning and through improved performance management.]]></note><topic position="1817,-260" order="0" text="Strategic Priority 2a: Personal Plans" id="113"><note><![CDATA[Each employee will have a personal Professional Development Plan. ]]></note></topic><topic position="1869,-236" order="1" text="Strategic Priority 2b: External learning matches organ. goals" id="114"><note><![CDATA[Each department of Freeform will identify areas that need development to meet overall FS goals. Eg. Project Manager may identify needed improvement in a development tool. Or... Bus. Dev. may identify a new need in NFP that FS could fill within mandate, if training were provided. Professional Dev. priority will be given to proposals for development with clear ROIs.]]></note></topic><topic position="1831,-212" order="2" text="Strategic Priority 2c: Learning Environment" id="116"><note><![CDATA[Learning and innovation are an essential part of providing the best solutions to NFPs. Cost effective internal learning and time to explore innovation will be encouraged, provided they conform with organization goal and clear ROI is demonstrated.]]></note></topic><topic position="1766,-188" order="3" text="So That..." id="112"><icon id="object_rainbow"/><note><![CDATA[(So that... our employees have improved skills and knowledge, So that... they are highly competent and can work well in agile teams and feel fulfilled and self actualized... So that we can so the best work possible, for the least cost, in the shortest time for other NFPs, So that... NFPs can help those who need it.)]]></note></topic></topic><topic position="1952,168" text="Strategy 4: Inclusive, Positive Environment" id="105"><note><![CDATA[Strategy #4: Foster a diverse, inclusive community with a positive work environment.]]></note><topic position="2229,142" order="0" text="Strategic Priority 4a:Feedback" id="119"><note><![CDATA[Conduct regular organizational feedback assessments and collaborate to improve the work climate]]></note></topic><topic position="2246,166" order="1" text="Strategic Priority 4b: Anti Harassment" id="120"><note><![CDATA[Educate employees on the prevention of harassment and discrimination and productive ways to resolve conflict]]></note></topic><topic position="2228,190" order="2" text="Strategic Priority 4c: Diversity" id="121"><note><![CDATA[Insure we promote our commitment to diversity and non-discrimination through our actions and in our outreach and employee recruitment efforts]]></note></topic><topic position="2178,214" order="3" id="253"/><topic position="2191,238" order="4" text="So That..." id="118"><icon id="object_rainbow"/><note><![CDATA[(So that... we can reflect the diverse populations we serve AND ensure everyone feels safe, respected and included, So that... we better serve our diverse client organizations AND we are a great place to work )]]></note></topic></topic><topic position="1326,-642" text="Strategy 1: Recruit &amp; Retain" id="29"><note><![CDATA[Recruit and retain top talent commensurate with identified organizational capacity requirements ]]></note><topic position="1444,-781" order="0" text="So that..." id="28"><note><![CDATA[(So that... we find and keep good people, So that... they are highly competent and can work well in agile teams... So that we can so the best work possible, for the least cost, in the shortest time for other NFPs, So that... NFPs can help those who need it.)]]></note></topic><topic position="1539,-742" order="1" text="Strategic Priority 1a: Recruitment" id="37"><note><![CDATA[1. Identify and use proactive and effective recruitment strategies, ]]></note><topic position="1573,-752" order="0" text="Modify App Form" shrink="true" id="238"><note><![CDATA[Recently, I saw a few job posts sent through different community
<map name="complex" version="tango"><topic central="true" text="PPM Plan" id="1" bgColor="#32e36a"><topic position="241,250" order="10" text="Business Development " id="4" fontStyle=";;;bold;;"/><topic position="226,-100" order="2" text="Backlog Management" shape="line" id="18" fontStyle=";;;bold;;"><link url="https://docs.google.com/a/freeform.ca/drawings/d/1mrtkVAN3_XefJJCgfxw4Va6xk9TVDBKXDt_uzyIF4Us/edit" urlType="url"/></topic><topic position="-193,50" order="5" text="Freeform IT" id="10" fontStyle=";;;bold;;"/><topic position="-271,-50" order="3" text="Client Project Management" id="204" fontStyle=";;;bold;;"/><topic position="-183,-150" order="7" text="Governance &amp; Executive" id="206" fontStyle=";;;bold;;"/><topic position="124,-200" order="8" text="Finance" id="5" fontStyle=";;;bold;;"/><topic position="176,-150" order="6" text="Administration" id="3" fontStyle=";;;bold;;"/><topic position="222,100" order="4" text="Human Resources" id="154" fontStyle=";;;bold;;"><note><![CDATA[HR Vision: Freeform Solutions is successful at its mission, sustainable as an organization AND is a great place to work.
HR Mission: To provide a positive HR service experience for applicants and employees, and collaborate with departments to recruit, develop, support, and retain diverse and talented employees who are the key to Freeforms reputation and success.]]></note></topic><topic position="-202,150" order="9" text="Freeform Hosting" id="16" fontStyle=";;;bold;;"/><topic position="197,50" order="0" text="Community Outreach" id="247" fontStyle=";;;bold;;"/><topic position="124,300" order="12" text="R&amp;D" id="261" fontStyle=";;;bold;;"><topic position="230,289" order="0" text="Goals" id="263"/><topic position="239,313" order="1" text="Formulize" id="264"/></topic><topic position="-158,0" order="1" text="Probono" id="268"><topic position="-273,1" order="0" id="269"/></topic></topic><topic position="1558,-249" text="Strategy 2: Talent Development" id="31"><note><![CDATA[Strategy #2: Support the talent development of our employees through professional development and learning and through improved performance management.]]></note><topic position="1817,-260" order="0" text="Strategic Priority 2a: Personal Plans" id="113"><note><![CDATA[Each employee will have a personal Professional Development Plan. ]]></note></topic><topic position="1869,-236" order="1" text="Strategic Priority 2b: External learning matches organ. goals" id="114"><note><![CDATA[Each department of Freeform will identify areas that need development to meet overall FS goals. Eg. Project Manager may identify needed improvement in a development tool. Or... Bus. Dev. may identify a new need in NFP that FS could fill within mandate, if training were provided. Professional Dev. priority will be given to proposals for development with clear ROIs.]]></note></topic><topic position="1831,-212" order="2" text="Strategic Priority 2c: Learning Environment" id="116"><note><![CDATA[Learning and innovation are an essential part of providing the best solutions to NFPs. Cost effective internal learning and time to explore innovation will be encouraged, provided they conform with organization goal and clear ROI is demonstrated.]]></note></topic><topic position="1766,-188" order="3" text="So That..." id="112"><icon id="object_rainbow"/><note><![CDATA[(So that... our employees have improved skills and knowledge, So that... they are highly competent and can work well in agile teams and feel fulfilled and self actualized... So that we can so the best work possible, for the least cost, in the shortest time for other NFPs, So that... NFPs can help those who need it.)]]></note></topic></topic><topic position="1952,168" text="Strategy 4: Inclusive, Positive Environment" id="105"><note><![CDATA[Strategy #4: Foster a diverse, inclusive community with a positive work environment.]]></note><topic position="2229,142" order="0" text="Strategic Priority 4a:Feedback" id="119"><note><![CDATA[Conduct regular organizational feedback assessments and collaborate to improve the work climate]]></note></topic><topic position="2246,166" order="1" text="Strategic Priority 4b: Anti Harassment" id="120"><note><![CDATA[Educate employees on the prevention of harassment and discrimination and productive ways to resolve conflict]]></note></topic><topic position="2228,190" order="2" text="Strategic Priority 4c: Diversity" id="121"><note><![CDATA[Insure we promote our commitment to diversity and non-discrimination through our actions and in our outreach and employee recruitment efforts]]></note></topic><topic position="2178,214" order="3" id="253"/><topic position="2191,238" order="4" text="So That..." id="118"><icon id="object_rainbow"/><note><![CDATA[(So that... we can reflect the diverse populations we serve AND ensure everyone feels safe, respected and included, So that... we better serve our diverse client organizations AND we are a great place to work )]]></note></topic></topic><topic position="1326,-642" text="Strategy 1: Recruit &amp; Retain" id="29"><note><![CDATA[Recruit and retain top talent commensurate with identified organizational capacity requirements ]]></note><topic position="1444,-781" order="0" text="So that..." id="28"><note><![CDATA[(So that... we find and keep good people, So that... they are highly competent and can work well in agile teams... So that we can so the best work possible, for the least cost, in the shortest time for other NFPs, So that... NFPs can help those who need it.)]]></note></topic><topic position="1539,-742" order="1" text="Strategic Priority 1a: Recruitment" id="37"><note><![CDATA[1. Identify and use proactive and effective recruitment strategies, ]]></note><topic position="1573,-752" order="0" text="Modify App Form" shrink="true" id="238"><note><![CDATA[Recently, I saw a few job posts sent through different community
groups and they seem to be taking our idea of screening candidates
to a next level. Not only they ask candidates to provide resume and
cover letter + some project related information but also request