Skip to content

Commit c267b3c

Browse files
rkaraivanovSisIvanovazdrawkuChronosSF
authored
Toolbar refactor (#8158)
* feat(grid-toolbar): Toolbar refactor Closes #8055 * feat(grid-toolbar): Hierarchical grid implementation Closes #8055 * refactor(grid-toolbar): Correctly grid context through templates in hierarchical grid * fix(grid): Deselect columns for hiding Change the interaction for column hiding UI. Updated tests. Closes #6858 * feat(grid): Emit when the grid is fully available in the DOM Closes #7924 * refactor(toolbar): Hierachical grid tweaks. Toolbar actions are rendered once the grid is 'fully' loaded in order to prevent expression changed after checked errors caused by updating the column collection. More unit tests updates. * chore(*): Dev demos updates * refactor(toolbar): Toolbar unit tests * refactor(tests): More unit tests * refactor(toolbar): Tests, api docs and tweaks * style(toolbar): provide styling for grid toolbar component * refactor(*): Unit tests * refactor(*): More unit tests * chore(styling): run stylelint --fix * refactor(toolbar): Even more unit tests * style(toolbar): update elevations, border & title width * update dropdowns border * refactor(toolbar): remove unnecessary selectors * refactor(toolbar): change elevation variable * docs(toolbar): remove unnecessary requires from sass docs * feat(grid-toolbar): Add basic migrations * feat(toolbar): Clean up migrations Migrate the toolbar based on the old input prop value * fix(migrations): File changes ordering * feat(toolbar): Template directive migration * fix(toolbar): Focus action comp input on open Remove filtering overlay keydown `catch'em all` handler. * feat(toolbar): Hierarchical grid migrations * fix(toolbar): Migration binding on empty directives * feat(toolbar): Migrate template context bindings * fix(toolbar): Backward compatible props * chore(toolbar): Unit tests tweaks * fix(toolbar): Toolbar width growing with pinned area * fix(toolbar): Expression changed error * fix(toolbar): Dropdown max height * fix(toolbar): Skip excel export dropdown * fix(toolbar): Choppy toggling of toolbar elements * refactor(toolbar): Address review comments Co-authored-by: Silvia Ivanova <[email protected]> Co-authored-by: Zdravko Kolev <[email protected]> Co-authored-by: Stamen Stoychev <[email protected]>
1 parent 1c3ae74 commit c267b3c

File tree

57 files changed

+1854
-1741
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1854
-1741
lines changed

projects/igniteui-angular/migrations/common/UpdateChanges.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ export class UpdateChanges {
147147
}
148148

149149
/** Add condition function. */
150-
public addCondition(conditionName: string, callback: (ownerMatch: string) => boolean) {
150+
public addCondition(conditionName: string, callback: (ownerMatch: string, path: string) => boolean) {
151151
this.conditionFunctions.set(conditionName, callback);
152152
}
153153

@@ -266,7 +266,7 @@ export class UpdateChanges {
266266

267267
for (const match of matches) {
268268
let replaceStatement = replace;
269-
if (!this.areConditionsFulfiled(match, change.conditions)) {
269+
if (!this.areConditionsFulfilled(match, change.conditions, entryPath)) {
270270
continue;
271271
}
272272

@@ -403,12 +403,12 @@ export class UpdateChanges {
403403
}
404404
}
405405

406-
private areConditionsFulfiled(match: string, conditions: string[]): boolean {
406+
private areConditionsFulfilled(match: string, conditions: string[], entryPath: string): boolean {
407407
if (conditions) {
408408
for (const condition of conditions) {
409409
if (this.conditionFunctions && this.conditionFunctions.has(condition)) {
410410
const callback = this.conditionFunctions.get(condition);
411-
if (callback && !callback(match)) {
411+
if (callback && !callback(match, entryPath)) {
412412
return false;
413413
}
414414
}

projects/igniteui-angular/migrations/common/util.ts

+160
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,19 @@ import * as path from 'path';
33
import { SchematicContext, Tree } from '@angular-devkit/schematics';
44
import { WorkspaceSchema, WorkspaceProject, ProjectType } from '@schematics/angular/utility/workspace-models';
55
import { execSync } from 'child_process';
6+
import {
7+
Attribute,
8+
Comment,
9+
Element,
10+
Expansion,
11+
ExpansionCase,
12+
getHtmlTagDefinition,
13+
HtmlParser,
14+
Node,
15+
Text,
16+
Visitor
17+
} from '@angular/compiler';
18+
import { replaceMatch } from './tsUtils';
619

720
const configPaths = ['/.angular.json', '/angular.json'];
821

@@ -111,3 +124,150 @@ export function tryUninstallPackage(context: SchematicContext, packageManager: s
111124
.warn(`Could not uninstall ${pkg}, you may want to uninstall it manually.`, JSON.parse(e));
112125
}
113126
}
127+
128+
interface TagOffset {
129+
start: number;
130+
end: number;
131+
}
132+
133+
export interface SourceOffset {
134+
startTag: TagOffset;
135+
endTag: TagOffset;
136+
file: {
137+
content: string;
138+
url: string;
139+
};
140+
node?: Element;
141+
}
142+
143+
144+
export class FileChange {
145+
146+
constructor(
147+
public position = 0,
148+
public text = '',
149+
public replaceText = '',
150+
public type: 'insert' | 'replace' = 'insert'
151+
) {}
152+
153+
apply(content: string) {
154+
if (this.type === 'insert') {
155+
return `${content.substring(0, this.position)}${this.text}${content.substring(this.position)}`;
156+
}
157+
return replaceMatch(content, this.replaceText, this.text, this.position);
158+
}
159+
}
160+
161+
/**
162+
* Parses an Angular template file/content and returns an array of the root nodes of the file.
163+
*
164+
* @param host
165+
* @param filePath
166+
* @param encoding
167+
*/
168+
export function parseFile(host: Tree, filePath: string, encoding = 'utf8') {
169+
return new HtmlParser().parse(host.read(filePath).toString(encoding), filePath).rootNodes;
170+
}
171+
172+
export function findElementNodes(root: Node[], tag: string | string[]): Node[] {
173+
const tags = new Set(Array.isArray(tag) ? tag : [tag]);
174+
return flatten(Array.isArray(root) ? root : [root])
175+
.filter((node: Element) => tags.has(node.name));
176+
}
177+
178+
export function hasAttribute(root: Element, attribute: string | string[]) {
179+
const attrs = Array.isArray(attribute) ? attribute : [attribute];
180+
return !!root.attrs.find(a => attrs.includes(a.name));
181+
}
182+
183+
export function getAttribute(root: Element, attribute: string | string[]) {
184+
const attrs = Array.isArray(attribute) ? attribute : [attribute];
185+
return root.attrs.filter(a => attrs.includes(a.name));
186+
}
187+
188+
export function getSourceOffset(element: Element): SourceOffset {
189+
const { startSourceSpan, endSourceSpan } = element;
190+
return {
191+
startTag: { start: startSourceSpan.start.offset, end: startSourceSpan.end.offset },
192+
endTag: { start: endSourceSpan.start.offset, end: endSourceSpan.end.offset },
193+
file: {
194+
content: startSourceSpan.start.file.content,
195+
url: startSourceSpan.start.file.url
196+
},
197+
node: element
198+
};
199+
}
200+
201+
202+
function isElement(node: Node | Element): node is Element {
203+
return (node as Element).children !== undefined;
204+
}
205+
206+
/**
207+
* Given an array of `Node` objects, flattens the ast tree to a single array.
208+
* De facto only `Element` type objects have children.
209+
*
210+
* @param list
211+
*/
212+
export function flatten(list: Node[]) {
213+
let node: Node;
214+
let r: Node[] = [];
215+
216+
for (let i = 0; i < list.length; i++) {
217+
node = list[i];
218+
r.push(node);
219+
220+
if (isElement(node)) {
221+
r = r.concat(flatten(node.children));
222+
}
223+
}
224+
return r;
225+
}
226+
227+
/**
228+
* https://github.com/angular/angular/blob/master/packages/compiler/test/ml_parser/util/util.ts
229+
*
230+
* May be useful for validating the output of our own migrations,
231+
*/
232+
class SerializerVisitor implements Visitor {
233+
234+
visitElement(element: Element, context: any): any {
235+
if (getHtmlTagDefinition(element.name).isVoid) {
236+
return `<${element.name}${this._visitAll(element.attrs, ' ')}/>`;
237+
}
238+
239+
return `<${element.name}${this._visitAll(element.attrs, ' ')}>${this._visitAll(element.children)}</${element.name}>`;
240+
}
241+
242+
visitAttribute(attribute: Attribute, context: any): any {
243+
return attribute.value === '' ? `${attribute.name}` : `${attribute.name}="${attribute.value}"`;
244+
}
245+
246+
visitText(text: Text, context: any): any {
247+
return text.value;
248+
}
249+
250+
visitComment(comment: Comment, context: any): any {
251+
return `<!--${comment.value}-->`;
252+
}
253+
254+
visitExpansion(expansion: Expansion, context: any): any {
255+
return `{${expansion.switchValue}, ${expansion.type},${this._visitAll(expansion.cases)}}`;
256+
}
257+
258+
visitExpansionCase(expansionCase: ExpansionCase, context: any): any {
259+
return ` ${expansionCase.value} {${this._visitAll(expansionCase.expression)}}`;
260+
}
261+
262+
private _visitAll(nodes: Node[], join: string = ''): string {
263+
if (nodes.length === 0) {
264+
return '';
265+
}
266+
return join + nodes.map(a => a.visit(this, null)).join(join);
267+
}
268+
}
269+
270+
271+
export function serializeNodes(nodes: Node[]): string[] {
272+
return nodes.map(node => node.visit(new SerializerVisitor(), null));
273+
}

projects/igniteui-angular/migrations/migration-collection.json

+5
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@
8585
"version": "10.2.0",
8686
"description": "Updates Ignite UI for Angular from v10.1.x to v10.2.0",
8787
"factory": "./update-10_2_0"
88+
},
89+
"migration-18": {
90+
"version": "11.0.0",
91+
"description": "Updates Ignite UI for Angular from v10.2.x to v11.0.0",
92+
"factory": "./update-11_0_0"
8893
}
8994
}
9095
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"@scheme": "../../common/schema/binding.schema.json",
3+
"changes": [
4+
{
5+
"name": "showToolbar",
6+
"remove": "true",
7+
"owner": {
8+
"selector": "igx-grid",
9+
"type": "component"
10+
}
11+
},
12+
{
13+
"name": "showToolbar",
14+
"remove": "true",
15+
"owner": {
16+
"selector": "igx-tree-grid",
17+
"type": "component"
18+
}
19+
},
20+
{
21+
"name": "showToolbar",
22+
"remove": "true",
23+
"owner": {
24+
"selector": "igx-hierarchical-grid",
25+
"type": "component"
26+
}
27+
},
28+
{
29+
"name": "showToolbar",
30+
"remove": "true",
31+
"owner": {
32+
"selector": "igx-row-island",
33+
"type": "component"
34+
}
35+
}
36+
]
37+
}

0 commit comments

Comments
 (0)