@projectcaluma/ember-distribution 1.0.0-beta.1 → 1.0.0-beta.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. package/CHANGELOG.md +130 -0
  2. package/addon/abilities/distribution.js +41 -0
  3. package/addon/abilities/inquiry.js +20 -0
  4. package/addon/components/cd-document-header.hbs +17 -0
  5. package/addon/components/cd-inquiry-answer-form.hbs +78 -0
  6. package/addon/components/{inquiry-answer-form.js → cd-inquiry-answer-form.js} +32 -14
  7. package/addon/components/cd-inquiry-dialog/inquiry-deadline.hbs +27 -0
  8. package/addon/components/{inquiry-dialog → cd-inquiry-dialog}/inquiry-deadline.js +5 -1
  9. package/addon/components/cd-inquiry-dialog/inquiry-divider.hbs +8 -0
  10. package/addon/components/{inquiry-dialog → cd-inquiry-dialog}/inquiry-divider.js +1 -1
  11. package/addon/components/cd-inquiry-dialog/inquiry-part.hbs +109 -0
  12. package/addon/components/cd-inquiry-dialog/inquiry-part.js +69 -0
  13. package/addon/components/cd-inquiry-dialog/inquiry.hbs +16 -0
  14. package/addon/components/cd-inquiry-dialog/inquiry.js +11 -0
  15. package/addon/components/cd-inquiry-dialog.hbs +30 -0
  16. package/addon/components/cd-inquiry-dialog.js +94 -0
  17. package/addon/components/cd-inquiry-edit-form.hbs +44 -0
  18. package/addon/components/{inquiry-edit-form.js → cd-inquiry-edit-form.js} +5 -4
  19. package/addon/components/cd-inquiry-new-form.hbs +125 -0
  20. package/addon/components/cd-inquiry-new-form.js +114 -0
  21. package/addon/components/cd-navigation/controls.hbs +41 -0
  22. package/addon/components/cd-navigation/controls.js +95 -0
  23. package/addon/components/cd-navigation/item.hbs +18 -0
  24. package/addon/components/{distribution-navigation → cd-navigation}/item.js +2 -2
  25. package/addon/components/cd-navigation/section.hbs +26 -0
  26. package/addon/components/{distribution-navigation → cd-navigation}/section.js +1 -1
  27. package/addon/components/cd-navigation/status-indicator.hbs +13 -0
  28. package/addon/components/{distribution-navigation → cd-navigation}/status-indicator.js +1 -1
  29. package/addon/components/cd-navigation.hbs +11 -0
  30. package/addon/components/cd-navigation.js +53 -0
  31. package/addon/components/cd-notfound.hbs +12 -0
  32. package/addon/components/cd-truncated.hbs +8 -0
  33. package/addon/components/cd-truncated.js +32 -0
  34. package/addon/config.js +12 -7
  35. package/addon/controllers/application.js +10 -0
  36. package/addon/controllers/{distribution/new.js → new.js} +2 -2
  37. package/addon/engine.js +7 -1
  38. package/addon/gql/fragments/inquiry.graphql +37 -12
  39. package/addon/gql/mutations/complete-work-item.graphql +8 -0
  40. package/addon/gql/mutations/withdraw-inquiry.graphql +8 -0
  41. package/addon/gql/queries/control-work-items.graphql +18 -2
  42. package/addon/gql/queries/incomplete-inquiries.graphql +13 -0
  43. package/addon/gql/queries/inquiry-answer.graphql +17 -12
  44. package/addon/gql/queries/inquiry-dialog.graphql +3 -2
  45. package/addon/gql/queries/inquiry-edit.graphql +2 -0
  46. package/addon/gql/queries/inquiry-navigation.graphql +4 -1
  47. package/addon/modifiers/pikaday.js +2 -0
  48. package/addon/routes/{distribution.js → application.js} +1 -1
  49. package/addon/routes/{distribution/index.js → index.js} +2 -2
  50. package/addon/routes/inquiry/detail/answer.js +7 -0
  51. package/addon/routes/inquiry/detail/index.js +7 -0
  52. package/addon/routes/{distribution/inquiry → inquiry}/detail.js +1 -1
  53. package/addon/routes/inquiry/index.js +10 -0
  54. package/addon/routes/{distribution/inquiry.js → inquiry.js} +1 -1
  55. package/addon/routes/new.js +7 -0
  56. package/addon/routes/notfound.js +3 -0
  57. package/addon/routes.js +5 -6
  58. package/addon/services/distribution.js +112 -0
  59. package/addon/templates/application.hbs +18 -0
  60. package/addon/templates/index.hbs +11 -0
  61. package/addon/templates/inquiry/detail/answer.hbs +1 -0
  62. package/addon/templates/inquiry/detail/index.hbs +1 -0
  63. package/addon/templates/{distribution/inquiry → inquiry}/detail.hbs +0 -0
  64. package/addon/templates/{distribution/inquiry → inquiry}/index.hbs +1 -1
  65. package/addon/templates/{distribution/inquiry.hbs → inquiry.hbs} +0 -0
  66. package/addon/templates/{distribution/new.hbs → new.hbs} +1 -1
  67. package/addon/templates/notfound.hbs +1 -0
  68. package/addon/utils/inquiry-answer-status.js +34 -0
  69. package/addon/utils/inquiry-deadline.js +6 -9
  70. package/addon/utils/inquiry-status.js +12 -7
  71. package/addon/utils/unique-by-groups.js +1 -0
  72. package/app/abilities/distribution.js +1 -0
  73. package/app/components/cd-document-header.js +1 -0
  74. package/app/components/{inquiry-dialog/inquiry.js → cd-inquiry-answer-form.js} +1 -1
  75. package/app/components/{inquiry-dialog → cd-inquiry-dialog}/inquiry-deadline.js +1 -1
  76. package/app/components/{inquiry-dialog → cd-inquiry-dialog}/inquiry-divider.js +1 -1
  77. package/app/components/{inquiry-dialog → cd-inquiry-dialog}/inquiry-part.js +1 -1
  78. package/app/components/{distribution-navigation.js → cd-inquiry-dialog/inquiry.js} +1 -1
  79. package/app/components/{inquiry-edit-form.js → cd-inquiry-dialog.js} +1 -1
  80. package/app/components/cd-inquiry-edit-form.js +1 -0
  81. package/app/components/{inquiry-answer-form.js → cd-inquiry-new-form.js} +1 -1
  82. package/app/components/cd-navigation/controls.js +1 -0
  83. package/app/components/cd-navigation/item.js +1 -0
  84. package/app/components/cd-navigation/section.js +1 -0
  85. package/app/components/{distribution-navigation/item.js → cd-navigation/status-indicator.js} +1 -1
  86. package/app/components/{inquiry-dialog.js → cd-navigation.js} +1 -1
  87. package/app/components/{icon-button.js → cd-notfound.js} +1 -1
  88. package/app/components/{inquiry-new-form.js → cd-truncated.js} +1 -1
  89. package/app/services/distribution.js +1 -0
  90. package/app/styles/@projectcaluma/ember-distribution.scss +3 -2
  91. package/app/styles/_answer-form.scss +4 -0
  92. package/app/styles/_group-list.scss +7 -0
  93. package/app/styles/_inquiry-divider.scss +22 -0
  94. package/app/styles/_truncated.scss +3 -0
  95. package/app/utils/inquiry-answer-status.js +1 -0
  96. package/index.js +10 -14
  97. package/package.json +31 -27
  98. package/public/assets/distribution.svg +1 -0
  99. package/translations/de.yaml +49 -8
  100. package/translations/en.yaml +50 -8
  101. package/translations/fr.yaml +49 -8
  102. package/addon/components/distribution-navigation/controls.hbs +0 -21
  103. package/addon/components/distribution-navigation/controls.js +0 -45
  104. package/addon/components/distribution-navigation/item.hbs +0 -18
  105. package/addon/components/distribution-navigation/section.hbs +0 -24
  106. package/addon/components/distribution-navigation/status-indicator.hbs +0 -17
  107. package/addon/components/distribution-navigation.hbs +0 -17
  108. package/addon/components/distribution-navigation.js +0 -81
  109. package/addon/components/icon-button.hbs +0 -20
  110. package/addon/components/icon-button.js +0 -22
  111. package/addon/components/inquiry-answer-form.hbs +0 -46
  112. package/addon/components/inquiry-dialog/inquiry-deadline.hbs +0 -6
  113. package/addon/components/inquiry-dialog/inquiry-divider.hbs +0 -7
  114. package/addon/components/inquiry-dialog/inquiry-part.hbs +0 -40
  115. package/addon/components/inquiry-dialog/inquiry-part.js +0 -20
  116. package/addon/components/inquiry-dialog/inquiry.hbs +0 -13
  117. package/addon/components/inquiry-dialog/inquiry.js +0 -7
  118. package/addon/components/inquiry-dialog.hbs +0 -9
  119. package/addon/components/inquiry-dialog.js +0 -42
  120. package/addon/components/inquiry-edit-form.hbs +0 -27
  121. package/addon/components/inquiry-new-form.hbs +0 -110
  122. package/addon/components/inquiry-new-form.js +0 -154
  123. package/addon/routes/distribution/inquiry/detail/answer.js +0 -7
  124. package/addon/routes/distribution/inquiry/detail/index.js +0 -7
  125. package/addon/routes/distribution/inquiry/index.js +0 -10
  126. package/addon/routes/distribution/new.js +0 -7
  127. package/addon/templates/distribution/inquiry/detail/answer.hbs +0 -1
  128. package/addon/templates/distribution/inquiry/detail/index.hbs +0 -1
  129. package/addon/templates/distribution.hbs +0 -8
  130. package/app/components/distribution-navigation/controls.js +0 -1
  131. package/app/components/distribution-navigation/section.js +0 -1
  132. package/app/components/distribution-navigation/status-indicator.js +0 -1
  133. package/app/styles/_icon-button.scss +0 -13
  134. package/app/styles/_status-indicator.scss +0 -31
@@ -1,42 +0,0 @@
1
- import Component from "@glimmer/component";
2
- import { queryManager } from "ember-apollo-client";
3
- import { dropTask } from "ember-concurrency";
4
- import { useTask } from "ember-resources";
5
-
6
- import config from "@projectcaluma/ember-distribution/config";
7
- import inquiryDialogQuery from "@projectcaluma/ember-distribution/gql/queries/inquiry-dialog.graphql";
8
-
9
- export default class InquiryDialogComponent extends Component {
10
- @config config;
11
-
12
- @queryManager apollo;
13
-
14
- get inquiries() {
15
- return this._inquiries.value?.allWorkItems.edges.map((edge) => edge.node);
16
- }
17
-
18
- _inquiries = useTask(this, this.fetchDialog, () => [
19
- this.args.from,
20
- this.args.to,
21
- this.args.caseId,
22
- this.config,
23
- ]);
24
-
25
- @dropTask
26
- *fetchDialog() {
27
- return yield this.apollo.watchQuery({
28
- query: inquiryDialogQuery,
29
- variables: {
30
- from: this.args.from,
31
- to: this.args.to,
32
- caseId: this.args.caseId,
33
- task: this.config.inquiry.task,
34
- infoQuestion: this.config.inquiry.infoQuestion,
35
- deadlineQuestion: this.config.inquiry.deadlineQuestion,
36
- statusQuestion: this.config.inquiry.answer.statusQuestion,
37
- answerInfoQuestion: this.config.inquiry.answer.infoQuestion,
38
- includeNavigationData: true,
39
- },
40
- });
41
- }
42
- }
@@ -1,27 +0,0 @@
1
- <CfContent
2
- @documentId={{decode-id this.inquiry.document.id}}
3
- @disabled={{cannot "edit inquiry" this.inquiry}}
4
- @loading={{this._inquiry.isRunning}}
5
- as |content|
6
- >
7
- <h1 class="uk-flex uk-flex-middle">
8
- {{t "caluma.distribution.edit.title"}}
9
- {{#if (eq this.inquiry.status "RUNNING")}}
10
- <UkLabel
11
- class="uk-margin-left"
12
- @label={{t "caluma.distribution.status.draft"}}
13
- />
14
- {{/if}}
15
- </h1>
16
-
17
- <content.form />
18
-
19
- <DocumentValidity @document={{content.document}} as |isValid validate|>
20
- <UkButton
21
- @type="submit"
22
- @color="primary"
23
- @disabled={{or (not isValid) this.send.isRunning}}
24
- @on-click={{perform this.send validate}}
25
- >{{t "caluma.distribution.edit.send"}}</UkButton>
26
- </DocumentValidity>
27
- </CfContent>
@@ -1,110 +0,0 @@
1
- <h1>{{t "caluma.distribution.new.title"}}</h1>
2
-
3
- {{#if this.selectedGroups.length}}
4
- <div class="uk-flex uk-flex-middle">
5
- <div class="uk-width-expand">
6
- <button type="button" class="uk-link uk-text-light">
7
- {{t "caluma.distribution.new.groups" count=this.selectedGroups.length}}
8
- </button>
9
- <div uk-dropdown class="uk-width-auto">
10
- <ul
11
- class="uk-list uk-list-bullet uk-margin-remove uk-padding-remove"
12
- data-test-selected-groups
13
- >
14
- {{#each this.selectedGroups as |identifier|}}
15
- <li class="uk-text-nowrap">{{group-name identifier}}</li>
16
- {{/each}}
17
- </ul>
18
- </div>
19
- {{t "caluma.distribution.new.selected" count=this.selectedGroups.length}}
20
- </div>
21
- <div>
22
- <UkButton
23
- @color="default"
24
- @label={{t "caluma.distribution.new.reset"}}
25
- @on-click={{this.clearSelectedGroups}}
26
- data-test-reset
27
- />
28
- <UkButton
29
- @color="primary"
30
- @label={{t "caluma.distribution.new.create-draft"}}
31
- @type="submit"
32
- @loading={{this.submit.isRunning}}
33
- @disabled={{this.submit.isRunning}}
34
- @on-click={{perform this.submit}}
35
- data-test-submit
36
- />
37
- </div>
38
- </div>
39
- <hr />
40
- {{/if}}
41
-
42
- <div class="uk-margin-bottom uk-button-group">
43
- {{#each-in this.config.new.types as |slug config|}}
44
- {{#unless config.disabled}}
45
- <UkButton
46
- data-test-type={{slug}}
47
- @label={{t config.label}}
48
- @color={{if (includes slug @selectedTypes) "primary" "default"}}
49
- @on-click={{fn this.updateSelectedTypes slug}}
50
- />
51
- {{/unless}}
52
- {{/each-in}}
53
- </div>
54
-
55
- <div class="uk-search uk-search-default uk-width-1-1">
56
- <span class="uk-search-icon-flip" uk-search-icon></span>
57
- <input
58
- placeholder={{t "caluma.distribution.new.search"}}
59
- aria-label={{t "caluma.distribution.new.search"}}
60
- class="uk-search-input"
61
- type="search"
62
- value={{@search}}
63
- data-test-search
64
- {{on "input" (perform this.updateSearch)}}
65
- />
66
- </div>
67
-
68
- {{#if this.groups.isRunning}}
69
- <div class="uk-text-center uk-margin">
70
- <UkSpinner @ratio={{2}} />
71
- </div>
72
- {{else if this.groups.value.length}}
73
- <ul class="uk-list uk-list-striped">
74
- {{#each this.groups.value as |group|}}
75
- {{! template-lint-disable require-presentational-children }}
76
- <li
77
- role="checkbox"
78
- class="uk-flex uk-flex-between uk-flex-middle"
79
- data-test-group={{group.identifier}}
80
- {{on "click" (fn this.updateSelectedGroups group.identifier)}}
81
- >
82
- {{! template-lint-disable no-nested-interactive }}
83
- <label for="group-{{group.identifier}}">
84
- <input
85
- type="checkbox"
86
- class="uk-checkbox uk-margin-small-right"
87
- checked={{includes group.identifier this.selectedGroups}}
88
- id="group-{{group.identifier}}"
89
- />
90
- {{group-name group.identifier}}
91
- </label>
92
- {{#if group.config.icon}}
93
- {{svg-jar
94
- group.config.icon
95
- width="20"
96
- height="20"
97
- class=(concat "uk-text-" group.config.iconColor)
98
- }}
99
- {{/if}}
100
- </li>
101
- {{/each}}
102
- </ul>
103
- {{else}}
104
- <div class="uk-text-center">
105
- <UkIcon @icon="search" @ratio={{10}} class="uk-margin-top" />
106
- <p class="uk-text-muted">
107
- {{t "caluma.distribution.new.empty"}}
108
- </p>
109
- </div>
110
- {{/if}}
@@ -1,154 +0,0 @@
1
- import { action } from "@ember/object";
2
- import { inject as service } from "@ember/service";
3
- import Component from "@glimmer/component";
4
- import { tracked } from "@glimmer/tracking";
5
- import { queryManager } from "ember-apollo-client";
6
- import { timeout, restartableTask, dropTask, task } from "ember-concurrency";
7
- import { useTask } from "ember-resources";
8
-
9
- import { decodeId } from "@projectcaluma/ember-core/helpers/decode-id";
10
- import config from "@projectcaluma/ember-distribution/config";
11
- import createInquiryMutation from "@projectcaluma/ember-distribution/gql/mutations/create-inquiry.graphql";
12
- import controlWorkItemsQuery from "@projectcaluma/ember-distribution/gql/queries/control-work-items.graphql";
13
- import inquiryNavigationQuery from "@projectcaluma/ember-distribution/gql/queries/inquiry-navigation.graphql";
14
-
15
- const toggle = (value, array) => {
16
- const set = new Set(array);
17
-
18
- set.delete(value) || set.add(value);
19
-
20
- return [...set];
21
- };
22
-
23
- export default class InquiryNewFormComponent extends Component {
24
- @service calumaOptions;
25
- @service notification;
26
- @service intl;
27
- @service router;
28
-
29
- @queryManager apollo;
30
-
31
- @config config;
32
-
33
- @tracked selectedGroups = [];
34
-
35
- groups = useTask(this, this.fetchGroups, () => [
36
- this.args.selectedTypes,
37
- this.args.search,
38
- ]);
39
-
40
- @action
41
- updateSelectedTypes(type, e) {
42
- e.preventDefault();
43
-
44
- this.args.onChangeSelectedTypes(toggle(type, this.args.selectedTypes));
45
- }
46
-
47
- @action
48
- updateSelectedGroups(identifier, e) {
49
- e.preventDefault();
50
-
51
- this.selectedGroups = toggle(identifier, this.selectedGroups);
52
- }
53
-
54
- @action
55
- clearSelectedGroups(e) {
56
- e.preventDefault();
57
-
58
- this.selectedGroups = [];
59
- }
60
-
61
- @restartableTask
62
- *updateSearch(e) {
63
- e.preventDefault();
64
-
65
- yield timeout(500);
66
-
67
- this.args.onChangeSearch(e.target.value);
68
- }
69
-
70
- @dropTask
71
- *submit(e) {
72
- e.preventDefault();
73
-
74
- if (!this.selectedGroups.length) return;
75
-
76
- try {
77
- // get create inquiry work item to complete, this will not trigger a
78
- // network request since it's already fetch in the controls
79
- const controlsData = yield this.apollo.watchQuery(
80
- {
81
- query: controlWorkItemsQuery,
82
- variables: {
83
- caseId: this.args.caseId,
84
- currentGroup: String(this.calumaOptions.currentGroupId),
85
- createTask: this.config.controls.createTask,
86
- completeTask: this.config.controls.completeTask,
87
- },
88
- },
89
- "create.edges"
90
- );
91
-
92
- // create new inquiries
93
- yield this.apollo.mutate({
94
- mutation: createInquiryMutation,
95
- variables: {
96
- id: decodeId(controlsData[0].node.id),
97
- context: JSON.stringify({
98
- addressed_groups: this.selectedGroups.map(String),
99
- }),
100
- },
101
- });
102
-
103
- // refetch navigation data
104
- const navigationData = yield this.apollo.query(
105
- {
106
- query: inquiryNavigationQuery,
107
- fetchPolicy: "network-only",
108
- variables: {
109
- caseId: this.args.caseId,
110
- task: this.config.inquiry.task,
111
- currentGroup: String(this.calumaOptions.currentGroupId),
112
- statusQuestion: this.config.inquiry.answer.statusQuestion,
113
- deadlineQuestion: this.config.inquiry.deadlineQuestion,
114
- includeNavigationData: true,
115
- },
116
- },
117
- "controlling.edges"
118
- );
119
-
120
- // transition to last added inquiry
121
- this.router.transitionTo("distribution.inquiry", {
122
- from: navigationData[0].node.controllingGroups[0],
123
- to: navigationData[0].node.addressedGroups[0],
124
- });
125
- } catch (e) {
126
- this.notification.danger(
127
- this.intl.t("caluma.distribution.new.error", {
128
- count: this.selectedGroups.length,
129
- })
130
- );
131
- }
132
- }
133
-
134
- @task
135
- *fetchGroups(types, search) {
136
- // https://github.com/ember-cli/eslint-plugin-ember/issues/1413
137
- yield Promise.resolve();
138
-
139
- const typedGroups = yield this.calumaOptions.fetchTypedGroups(
140
- types,
141
- search
142
- );
143
-
144
- return Object.entries(typedGroups)
145
- .flatMap(([type, groups]) => {
146
- return groups.map((group) => ({
147
- identifier: group[this.calumaOptions.groupIdentifierProperty],
148
- name: group[this.calumaOptions.groupNameProperty],
149
- config: this.config.new.types[type],
150
- }));
151
- })
152
- .sort((a, b) => a.name.localeCompare(b.name));
153
- }
154
- }
@@ -1,7 +0,0 @@
1
- import Route from "@ember/routing/route";
2
-
3
- export default class DistributionInquiryDetailAnswerRoute extends Route {
4
- model() {
5
- return this.modelFor("distribution.inquiry.detail");
6
- }
7
- }
@@ -1,7 +0,0 @@
1
- import Route from "@ember/routing/route";
2
-
3
- export default class DistributionInquiryDetailIndexRoute extends Route {
4
- model() {
5
- return this.modelFor("distribution.inquiry.detail");
6
- }
7
- }
@@ -1,10 +0,0 @@
1
- import Route from "@ember/routing/route";
2
-
3
- export default class DistributionInquiryIndexRoute extends Route {
4
- model() {
5
- return {
6
- ...this.modelFor("distribution.inquiry"),
7
- case: this.modelFor("distribution"),
8
- };
9
- }
10
- }
@@ -1,7 +0,0 @@
1
- import Route from "@ember/routing/route";
2
-
3
- export default class DistributionNewRoute extends Route {
4
- model() {
5
- return this.modelFor("distribution");
6
- }
7
- }
@@ -1 +0,0 @@
1
- <InquiryAnswerForm @inquiry={{@model}} />
@@ -1 +0,0 @@
1
- <InquiryEditForm @inquiry={{@model}} />
@@ -1,8 +0,0 @@
1
- <div uk-grid>
2
- <div class="uk-width-1-3">
3
- <DistributionNavigation @caseId={{@model}} />
4
- </div>
5
- <div class="uk-width-2-3">
6
- {{outlet}}
7
- </div>
8
- </div>
@@ -1 +0,0 @@
1
- export { default } from "@projectcaluma/ember-distribution/components/distribution-navigation/controls";
@@ -1 +0,0 @@
1
- export { default } from "@projectcaluma/ember-distribution/components/distribution-navigation/section";
@@ -1 +0,0 @@
1
- export { default } from "@projectcaluma/ember-distribution/components/distribution-navigation/status-indicator";
@@ -1,13 +0,0 @@
1
- @import "ember-uikit/variables-theme";
2
-
3
- @for $i from 1 through 8 {
4
- @each $side in "top", "right", "bottom", "left" {
5
- .uk-icon-button--gutter-#{$side}-#{$i} > svg {
6
- margin-#{$side}: #{$i}px !important;
7
- }
8
- }
9
-
10
- .uk-icon-button--gutter-#{$i} > svg {
11
- margin: #{$i}px;
12
- }
13
- }
@@ -1,31 +0,0 @@
1
- @import "ember-uikit/variables-theme";
2
-
3
- $size: $global-small-font-size * 1.2;
4
- $iconSize: $global-small-font-size * 0.9;
5
-
6
- $colors: (
7
- muted: $text-muted-color,
8
- emphasis: $text-emphasis-color,
9
- success: $text-success-color,
10
- danger: $text-danger-color,
11
- warning: $text-warning-color,
12
- );
13
-
14
- .status-indicator {
15
- width: $size;
16
- height: $size;
17
- border-width: 1px;
18
- border-style: solid;
19
-
20
- > svg {
21
- width: $iconSize;
22
- height: $iconSize;
23
- }
24
-
25
- @each $colorName, $color in $colors {
26
- &.uk-text-#{$colorName} {
27
- color: darken($color, 20%);
28
- border-color: $color;
29
- }
30
- }
31
- }