Skip to content

Commit 3e11fe7

Browse files
mateusjmafjhonyeduardo
authored andcommitted
feat(rich-text): possibilita que usuário mude a cor do texto
Adicionada a função de alterar a cor do texto através de um novo botão na toolbar do componente, no qual executará as funções nativas de seleção de cores do navegador e aplicará ao texto selecionado e/ou as próximas digitações. Fixes DTHFUI-1718
1 parent c06e7c9 commit 3e11fe7

File tree

9 files changed

+230
-46
lines changed

9 files changed

+230
-46
lines changed

projects/ui/src/lib/components/po-field/po-field.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { PoDisclaimerModule } from './../po-disclaimer/po-disclaimer.module';
99
import { PoLoadingModule } from '../../components/po-loading/index';
1010
import { PoModalModule } from '../../components/po-modal/po-modal.module';
1111
import { PoTableModule } from '../../components/po-table/po-table.module';
12+
import { PoTooltipModule } from './../../directives/po-tooltip/po-tooltip.module';
1213

1314
import { PoCalendarComponent } from './po-datepicker/po-calendar/po-calendar.component';
1415
import { PoCheckboxGroupComponent } from './po-checkbox-group/po-checkbox-group.component';
@@ -67,6 +68,7 @@ import { PoUrlComponent } from './po-url/po-url.component';
6768
PoModalModule,
6869
PoServicesModule,
6970
PoTableModule,
71+
PoTooltipModule
7072
],
7173
exports: [
7274
PoCheckboxGroupComponent,

projects/ui/src/lib/components/po-field/po-rich-text/po-rich-text-base.component.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import { requiredFailed } from '../validators';
1010
* O componente `po-rich-text` é um editor de textos enriquecidos.
1111
*
1212
* Para edição de texto simples sem formatação recomenda-se o uso do componente [**po-textarea**](/documentation/po-textarea).
13+
*
14+
* > No navegador Internet Explorer não é possível alterar a cor do texto.
1315
*/
1416
export abstract class PoRichTextBaseComponent implements ControlValueAccessor, Validator {
1517

projects/ui/src/lib/components/po-field/po-rich-text/po-rich-text-body/po-rich-text-body.component.spec.ts

Lines changed: 49 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ describe('PoRichTextBodyComponent:', () => {
2828
expect(component).toBeTruthy();
2929
});
3030

31-
describe('Methods: ', () => {
31+
describe('Methods:', () => {
3232

3333
it('onInit: should update `bodyElement`', () => {
3434
const expectedValue = 'on';
@@ -46,41 +46,56 @@ describe('PoRichTextBodyComponent:', () => {
4646
expect(component['updateValueWithModelValue']).toHaveBeenCalled();
4747
}));
4848

49-
it('executeCommand: should call `focus`', () => {
50-
const spyFocus = spyOn(component.bodyElement.nativeElement, <any> 'focus');
51-
const fakeValue = 'p';
49+
describe('executeCommand:', () => {
5250

53-
component.executeCommand(fakeValue);
51+
it('should call `focus`', () => {
52+
const spyFocus = spyOn(component.bodyElement.nativeElement, <any> 'focus');
53+
const fakeValue = 'p';
5454

55-
expect(spyFocus).toHaveBeenCalled();
56-
});
55+
component.executeCommand(fakeValue);
5756

58-
it('executeCommand: should call `execCommand`', () => {
59-
const spyExecCommand = spyOn(component.bodyElement.nativeElement, <any> 'focus');
60-
const fakeValue = 'p';
57+
expect(spyFocus).toHaveBeenCalled();
58+
});
6159

62-
component.executeCommand(fakeValue);
60+
it('should call `execCommand` with string as parameter.', () => {
61+
const spyExecCommand = spyOn(document, <any> 'execCommand');
62+
const fakeValue = 'p';
6363

64-
expect(spyExecCommand).toHaveBeenCalled();
65-
});
64+
component.executeCommand(fakeValue);
6665

67-
it('executeCommand: should call `updateModel`', () => {
68-
const fakeValue = 'p';
69-
spyOn(component, <any>'updateModel');
66+
expect(spyExecCommand).toHaveBeenCalledWith(fakeValue, false, null);
67+
});
7068

71-
component.executeCommand(fakeValue);
69+
it('should call `execCommand` with object as parameter.', () => {
70+
const command = 'foreColor';
71+
const value = '#000000';
72+
const spyExecCommand = spyOn(document, <any> 'execCommand');
73+
const fakeValue = { command, value } ;
7274

73-
expect(component['updateModel']).toHaveBeenCalled();
74-
});
75+
component.executeCommand(fakeValue);
7576

76-
it('executeCommand: should call `value.emit` with `modelValue`', () => {
77-
component.modelValue = 'teste';
78-
const fakeValue = 'p';
77+
expect(spyExecCommand).toHaveBeenCalledWith(fakeValue.command, false, fakeValue.value);
78+
});
7979

80-
spyOn(component.value, 'emit');
81-
component.executeCommand(fakeValue);
80+
it('should call `updateModel`', () => {
81+
const fakeValue = 'p';
82+
spyOn(component, <any>'updateModel');
83+
84+
component.executeCommand(fakeValue);
85+
86+
expect(component['updateModel']).toHaveBeenCalled();
87+
});
88+
89+
it('should call `value.emit` with `modelValue`', () => {
90+
component.modelValue = 'teste';
91+
const fakeValue = 'p';
92+
93+
spyOn(component.value, 'emit');
94+
component.executeCommand(fakeValue);
95+
96+
expect(component.value.emit).toHaveBeenCalledWith(component.modelValue);
97+
});
8298

83-
expect(component.value.emit).toHaveBeenCalledWith(component.modelValue);
8499
});
85100

86101
it('onClick: should call `emitSelectionCommands`', () => {
@@ -170,6 +185,14 @@ describe('PoRichTextBodyComponent:', () => {
170185
expect(component['valueBeforeChange']).toBe('value');
171186
});
172187

188+
it('rgbToHex: should return the hexadecimal value`', () => {
189+
const rbg = 'rgb(0, 128, 255)';
190+
const hex = '#0080ff';
191+
const result = component['rgbToHex'](rbg);
192+
193+
expect(result).toBe(hex);
194+
});
195+
173196
it('onBlur: should emit modelValue change', fakeAsync((): void => {
174197
const fakeThis = {
175198
modelValue: 'value',
@@ -212,7 +235,7 @@ describe('PoRichTextBodyComponent:', () => {
212235

213236
});
214237

215-
describe('Templates: ', () => {
238+
describe('Templates:', () => {
216239

217240
it('should contain `po-rich-text-body`', () => {
218241

projects/ui/src/lib/components/po-field/po-rich-text/po-rich-text-body/po-rich-text-body.component.ts

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,15 @@ export class PoRichTextBodyComponent implements OnInit {
3636
setTimeout(() => this.updateValueWithModelValue());
3737
}
3838

39-
executeCommand(command: string) {
39+
executeCommand(command: (string | { command: any, value: string })) {
4040
this.bodyElement.nativeElement.focus();
41-
document.execCommand(command, false, null);
41+
42+
if (typeof (command) === 'object') {
43+
document.execCommand(command.command, false, command.value);
44+
} else {
45+
document.execCommand(command, false, null);
46+
}
47+
4248
this.updateModel();
4349
this.value.emit(this.modelValue);
4450
}
@@ -79,8 +85,31 @@ export class PoRichTextBodyComponent implements OnInit {
7985

8086
private emitSelectionCommands() {
8187
const commands = poRichTextBodyCommands.filter(command => document.queryCommandState(command));
88+
const rgbColor = document.queryCommandValue('ForeColor');
89+
const hexColor = this.rgbToHex(rgbColor);
90+
this.commands.emit({commands, hexColor});
91+
}
92+
93+
private rgbToHex(rgb) {
94+
// Tratamento necessário para converter o código rgb para hexadecimal.
95+
const sep = rgb.indexOf(',') > -1 ? ',' : ' ';
96+
rgb = rgb.substr(4).split(')')[0].split(sep);
97+
98+
let r = (+rgb[0]).toString(16);
99+
let g = (+rgb[1]).toString(16);
100+
let b = (+rgb[2]).toString(16);
101+
102+
if (r.length === 1) {
103+
r = '0' + r;
104+
}
105+
if (g.length === 1) {
106+
g = '0' + g;
107+
}
108+
if (b.length === 1) {
109+
b = '0' + b;
110+
}
82111

83-
this.commands.emit(commands);
112+
return '#' + r + g + b;
84113
}
85114

86115
private updateModel() {

projects/ui/src/lib/components/po-field/po-rich-text/po-rich-text-literals.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export const poRichTextLiteralsDefault = {
77
center: 'Center',
88
right: 'Right',
99
justify: 'Justify',
10+
textColor: 'Text color',
1011
unorderedList: 'Bulleted list'
1112
},
1213
es: {
@@ -17,6 +18,7 @@ export const poRichTextLiteralsDefault = {
1718
center: 'Centro',
1819
right: 'Derecha',
1920
justify: 'Justificado',
21+
textColor: 'Color del texto',
2022
unorderedList: 'Lista con viñetas'
2123
},
2224
pt: {
@@ -27,6 +29,7 @@ export const poRichTextLiteralsDefault = {
2729
center: 'Centro',
2830
right: 'Direita',
2931
justify: 'Justificado',
32+
textColor: 'Cor do texto',
3033
unorderedList: 'Lista com marcadores'
3134
}
3235
};

projects/ui/src/lib/components/po-field/po-rich-text/po-rich-text-toolbar/po-rich-text-toolbar.component.html

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,21 @@
44
</po-button-group>
55
</div>
66

7+
<div *ngIf="!isInternetExplorer" class="po-rich-text-toolbar-button-align">
8+
<div class="po-rich-text-toolbar-color-picker-container">
9+
<button class="po-button po-text-ellipsis po-rich-text-toolbar-color-picker-button"
10+
[disabled]="readonly"
11+
[p-tooltip]="literals.textColor">
12+
<input
13+
#colorPickerInput
14+
class="po-rich-text-toolbar-color-picker-input"
15+
type="color"
16+
[disabled]="readonly"
17+
(change)="changeTextColor($event.target.value)">
18+
</button>
19+
</div>
20+
</div>
21+
722
<div class="po-rich-text-toolbar-button-align">
823
<po-button-group p-toggle="single" [p-buttons]="alignButtons">
924
</po-button-group>

0 commit comments

Comments
 (0)