[34070] Improve board creation modal (#8639)

* adding images to tile of each board

* Add path helper to resolve images

* improve the new board modal display

* solve travis check errors

* reduce additional unnecessary code

Co-authored-by: Oliver Günther <mail@oliverguenther.de>
pull/8664/head
Behrokh Satarnejad 4 years ago committed by GitHub
parent 6881f3d347
commit 35da772864
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 18
      frontend/src/app/helpers/images/path-helper.ts
  2. 13
      frontend/src/app/modules/boards/board/board-actions/assignee/assignee-action.service.ts
  3. 5
      frontend/src/app/modules/boards/board/board-actions/board-action.service.ts
  4. 2
      frontend/src/app/modules/boards/board/board-actions/board-actions-registry.service.ts
  5. 9
      frontend/src/app/modules/boards/board/board-actions/status/status-action.service.ts
  6. 7
      frontend/src/app/modules/boards/board/board-actions/subproject/subproject-action.service.ts
  7. 6
      frontend/src/app/modules/boards/board/board-actions/subtasks/board-subtasks-action.service.ts
  8. 9
      frontend/src/app/modules/boards/board/board-actions/version/version-action.service.ts
  9. 36
      frontend/src/app/modules/boards/new-board-modal/new-board-modal.component.ts
  10. 20
      frontend/src/app/modules/boards/tile-view/tile-view.component.html
  11. 32
      frontend/src/app/modules/boards/tile-view/tile-view.component.sass
  12. 15
      frontend/src/app/modules/boards/tile-view/tile-view.component.spec.ts
  13. 1
      frontend/src/app/modules/boards/tile-view/tile-view.component.ts
  14. 5
      frontend/src/assets/images/board_creation_modal/assignees.svg
  15. 17
      frontend/src/assets/images/board_creation_modal/lists.svg
  16. 14
      frontend/src/assets/images/board_creation_modal/parent-child.svg
  17. 12
      frontend/src/assets/images/board_creation_modal/status.svg
  18. 18
      frontend/src/assets/images/board_creation_modal/subproject.svg
  19. 13
      frontend/src/assets/images/board_creation_modal/version.svg
  20. 24
      modules/boards/config/locales/js-en.yml
  21. 8
      modules/boards/spec/features/action_boards/subtasks_board_spec.rb
  22. 4
      modules/boards/spec/features/support/board_index_page.rb

@ -0,0 +1,18 @@
export namespace ImageHelpers {
/**
* Returns an absolute asset path from the assets/images/ folder
*
* e.g., to access:
* frontend/src/assets/images/board_creation_modal/assignees.svg
*
* use
* imagePath('board_creation_modal/assignees.svg')
*
*
* @param image Path to the image starting from frontend/src/assets/images
*/
export function imagePath(image:string) {
return __webpack_public_path__ + 'assets/images/' + image;
}
}

@ -6,24 +6,25 @@ import {ProjectResource} from "core-app/modules/hal/resources/project-resource";
import {CachedBoardActionService} from "core-app/modules/boards/board/board-actions/cached-board-action.service";
import {HalResource} from "core-app/modules/hal/resources/hal-resource";
import {Board} from "core-app/modules/boards/board/board";
import {ApiV3Filter, FilterOperator} from "core-components/api/api-v3/api-v3-filter-builder";
import {ApiV3Filter} from "core-components/api/api-v3/api-v3-filter-builder";
import {QueryResource} from "core-app/modules/hal/resources/query-resource";
import {ImageHelpers} from "core-app/helpers/images/path-helper";
import imagePath = ImageHelpers.imagePath;
@Injectable()
export class BoardAssigneeActionService extends CachedBoardActionService {
filterName = 'assignee';
text = this.I18n.t('js.boards.board_type.action_by_attribute',
{ attribute: this.I18n.t('js.boards.board_type.action_type.assignee')});
text = this.I18n.t('js.boards.board_type.action_type.assignee');
description = this.I18n.t('js.boards.board_type.action_text',
{ attribute: this.I18n.t('js.boards.board_type.action_type.assignee')});
description = this.I18n.t('js.boards.board_type.action_text_assignee');
label = this.I18n.t('js.boards.add_list_modal.labels.assignee');
icon = 'icon-user';
image = ImageHelpers.imagePath('board_creation_modal/assignees.svg');
readonly unassignedUser:any = {
id: null,
href: null,

@ -55,6 +55,11 @@ export abstract class BoardActionService {
*/
description:string;
/**
* The description used in tile
*/
image:string;
/**
* Label used to describe the values in the modal
*/

@ -12,7 +12,7 @@ export class BoardActionsRegistryService {
public available() {
return _.map(this.mapping, (service:BoardActionService, attribute:string) => {
return { attribute: attribute, text: service.localizedName, icon:'', description:'' };
return { attribute: attribute, text: service.localizedName, icon:'', description:'', image:''};
});
}

@ -4,21 +4,22 @@ import {StatusResource} from "core-app/modules/hal/resources/status-resource";
import {BoardActionService} from "core-app/modules/boards/board/board-actions/board-action.service";
import {CachedBoardActionService} from "core-app/modules/boards/board/board-actions/cached-board-action.service";
import {StatusBoardHeaderComponent} from "core-app/modules/boards/board/board-actions/status/status-board-header.component";
import {ImageHelpers} from "core-app/helpers/images/path-helper";
@Injectable()
export class BoardStatusActionService extends CachedBoardActionService {
filterName = 'status';
text = this.I18n.t('js.boards.board_type.action_by_attribute',
{ attribute: this.I18n.t('js.boards.board_type.action_type.status')});
text = this.I18n.t('js.boards.board_type.action_type.status');
description = this.I18n.t('js.boards.board_type.action_text',
{ attribute: this.I18n.t('js.boards.board_type.action_type.status')});
description = this.I18n.t('js.boards.board_type.action_text_status');
label = this.I18n.t('js.boards.add_list_modal.labels.status');
icon = 'icon-workflow';
image = ImageHelpers.imagePath('board_creation_modal/status.svg');
public get localizedName() {
return this.I18n.t('js.work_packages.properties.status');
}

@ -4,18 +4,17 @@ import {HalResource} from "core-app/modules/hal/resources/hal-resource";
import {buildApiV3Filter} from "core-components/api/api-v3/api-v3-filter-builder";
import {UserResource} from 'core-app/modules/hal/resources/user-resource';
import {CollectionResource} from 'core-app/modules/hal/resources/collection-resource';
import {input} from "reactivestates";
import {WorkPackageChangeset} from "core-components/wp-edit/work-package-changeset";
import {WorkPackageResource} from "core-app/modules/hal/resources/work-package-resource";
import {SubprojectBoardHeaderComponent} from "core-app/modules/boards/board/board-actions/subproject/subproject-board-header.component";
import {CachedBoardActionService} from "core-app/modules/boards/board/board-actions/cached-board-action.service";
import {ImageHelpers} from "core-app/helpers/images/path-helper";
@Injectable()
export class BoardSubprojectActionService extends CachedBoardActionService {
filterName = 'onlySubproject';
text = this.I18n.t('js.boards.board_type.action_by_attribute',
{ attribute: this.I18n.t('js.boards.board_type.action_type.subproject')}) ;
text = this.I18n.t('js.boards.board_type.action_type.subproject');
description = this.I18n.t('js.boards.board_type.action_text_subprojects');
@ -23,6 +22,8 @@ export class BoardSubprojectActionService extends CachedBoardActionService {
icon = 'icon-projects';
image = ImageHelpers.imagePath('board_creation_modal/subproject.svg');
get localizedName() {
return this.I18n.t('js.work_packages.properties.subproject');
}

@ -8,13 +8,13 @@ import {ApiV3FilterBuilder} from "core-components/api/api-v3/api-v3-filter-build
import {SubtasksBoardHeaderComponent} from "core-app/modules/boards/board/board-actions/subtasks/subtasks-board-header.component";
import {QueryResource} from "core-app/modules/hal/resources/query-resource";
import {WorkPackageChangeset} from "core-components/wp-edit/work-package-changeset";
import {ImageHelpers} from "core-app/helpers/images/path-helper";
@Injectable()
export class BoardSubtasksActionService extends BoardActionService {
filterName = 'parent';
text = this.I18n.t('js.boards.board_type.action_by_attribute',
{ attribute: this.I18n.t('js.boards.board_type.action_type.subtasks') });
text = this.I18n.t('js.boards.board_type.action_type.subtasks');
description = this.I18n.t('js.boards.board_type.action_text_subtasks');
@ -22,6 +22,8 @@ export class BoardSubtasksActionService extends BoardActionService {
icon = 'icon-hierarchy';
image = ImageHelpers.imagePath('board_creation_modal/parent-child.svg');
public get localizedName() {
return this.I18n.t('js.boards.board_type.action_type.subtasks');
}

@ -13,6 +13,7 @@ import {VersionBoardHeaderComponent} from "core-app/modules/boards/board/board-a
import {FormResource} from "core-app/modules/hal/resources/form-resource";
import {InjectField} from "core-app/helpers/angular/inject-field.decorator";
import {CachedBoardActionService} from "core-app/modules/boards/board/board-actions/cached-board-action.service";
import {ImageHelpers} from "core-app/helpers/images/path-helper";
@Injectable()
export class BoardVersionActionService extends CachedBoardActionService {
@ -21,16 +22,16 @@ export class BoardVersionActionService extends CachedBoardActionService {
filterName = 'version';
text = this.I18n.t('js.boards.board_type.action_by_attribute',
{ attribute: this.I18n.t('js.boards.board_type.action_type.version')});
text = this.I18n.t('js.boards.board_type.action_type.version');
description = this.I18n.t('js.boards.board_type.action_text',
{ attribute: this.I18n.t('js.boards.board_type.action_type.version')});
description = this.I18n.t('js.boards.board_type.action_text_version');
label = this.I18n.t('js.boards.add_list_modal.labels.version');
icon = 'icon-getting-started';
image = ImageHelpers.imagePath('board_creation_modal/version.svg');
private writable$:Promise<boolean>;
public get localizedName() {

@ -37,7 +37,9 @@ import {BoardService} from "core-app/modules/boards/board/board.service";
import {BoardActionsRegistryService} from "core-app/modules/boards/board/board-actions/board-actions-registry.service";
import {LoadingIndicatorService} from "core-app/modules/common/loading-indicator/loading-indicator.service";
import {HalResourceNotificationService} from "core-app/modules/hal/services/hal-resource-notification.service";
import { ITileViewEntry } from '../tile-view/tile-view.component';
import {ITileViewEntry} from '../tile-view/tile-view.component';
import {ImageHelpers} from "core-app/helpers/images/path-helper";
import imagePath = ImageHelpers.imagePath;
@Component({
@ -85,19 +87,26 @@ export class NewBoardModalComponent extends OpModalComponent {
public createBoard(attribute:string) {
if (attribute === 'basic') {
this.createFree();
}
else {
this.createFree();
} else {
this.createAction(attribute);
}
}
private initiateTiles() {
this.available.unshift({attribute:'basic', text:this.text.free_board,
icon:'icon-boards', description:this.text.free_board_text});
this.available.unshift({
attribute: 'basic',
text: this.text.free_board,
icon: 'icon-boards',
description: this.text.free_board_text,
image: imagePath('board_creation_modal/lists.svg')
});
this.addIcon(this.available);
this.addDescription(this.available);
this.addText(this.available);
this.addImage(this.available);
}
private createFree() {
this.create({ type: 'free' });
}
@ -121,13 +130,16 @@ export class NewBoardModalComponent extends OpModalComponent {
this.halNotification.handleRawError(error);
});
}
private addDescription(tiles:ITileViewEntry[]) {
tiles.forEach(element => {
if (element.attribute !== 'basic') {
const service = this.boardActionRegistry.get(element.attribute!);
element.description = service.description; }
element.description = service.description;
}
});
}
private addIcon(tiles:ITileViewEntry[]) {
tiles.forEach(element => {
if (element.attribute !== 'basic') {
@ -136,6 +148,7 @@ export class NewBoardModalComponent extends OpModalComponent {
}
});
}
private addText(tiles:ITileViewEntry[]) {
tiles.forEach(element => {
if (element.attribute !== 'basic') {
@ -144,4 +157,13 @@ export class NewBoardModalComponent extends OpModalComponent {
}
});
}
private addImage(tiles:ITileViewEntry[]) {
tiles.forEach(element => {
if (element.attribute !== 'basic') {
const service = this.boardActionRegistry.get(element.attribute!);
element.image = service.image;
}
});
}
}

@ -1,14 +1,12 @@
<div class="tile-blocks--container">
<div class="tile-block button"
[disabled]="disabled()"
(accessibleClick)="created(tile.attribute)"
*ngFor="let tile of tiles">
<div class="row tile-block-header">
<i class="tile-block--icon icon3" [ngClass]="tile.icon" aria-hidden="true"></i>
<span>{{ tile.text | titlecase}}</span>
</div>
<p [textContent]="tile.description"></p>
<div class="tile-block button row"
[disabled]="disabled()"
(accessibleClick)="created(tile.attribute)"
*ngFor="let tile of tiles">
<img [src]="tile.image" class="tile-block-image"/>
<div>
<span class="tile-block-title">{{ tile.text | titlecase}}</span>
<p class="tile-block-description" [textContent]="tile.description"></p>
</div>
</div>
</div>

@ -1,32 +1,40 @@
.tile-blocks--container
display: grid
grid-template: repeat(auto-fit, 220px) / repeat(auto-fit, 450px)
grid-auto-rows: 220px
grid-template: repeat(auto-fit, 200px) / repeat(auto-fit, 450px)
grid-auto-rows: 200px
grid-column-gap: 10px
grid-row-gap: 10px
min-width: 500px
margin: 5px
min-width: 910px
.tile-block
border-radius: 3px
border-radius: 10px
display: grid
grid-template: 95px 1fr / 1fr
grid-template-columns: auto 1fr auto
grid-template-rows: auto
grid-row-gap: 5px
justify-items: left
background: #f8f8f8
background: #f7fafc
&:hover
outline: 1px solid grey
text-decoration: none
border: 1px solid grey
border-radius: 10px !important
cursor: pointer
.tile-block--icon
font-size: 50px
.tile-block-header
padding-left: 10px
.tile-block-title
padding-top: 30px
color: var(--primary-color-dark)
display: flex
align-items: center
display: block
text-align: left
font-weight: bolder
.tile-block p
text-align: left
text-align: left
width: 90%

@ -2,6 +2,8 @@ import {ComponentFixture, TestBed, async} from '@angular/core/testing';
import {DebugElement} from '@angular/core';
import {By} from '@angular/platform-browser';
import {TileViewComponent} from './tile-view.component';
import {ImageHelpers} from "core-app/helpers/images/path-helper";
import imagePath = ImageHelpers.imagePath;
describe('shows tiles', () => {
let app:TileViewComponent;
@ -9,8 +11,11 @@ describe('shows tiles', () => {
let element:DebugElement;
let tilesStub = [{
attribute: 'basic', text: 'Basic board',
icon: 'icon-boards', description: `Create a board in which you can freely
attribute: 'basic',
text: 'Basic board',
icon: 'icon-boards',
image: imagePath('board_creation_modal/lists.svg'),
description: `Create a board in which you can freely
create lists and order your work packages within.
Moving work packages between lists do not change the work package itself.`
}];
@ -37,13 +42,13 @@ describe('shows tiles', () => {
it('should show each tile', () => {
fixture.detectChanges();
let tile:HTMLElement = element.query(By.css('.tile-block')).nativeElement;
expect(tile.textContent).toContain('Basic Board');
expect(tile.textContent).toContain('Basic');
});
it('should show the icon', () => {
it('should show the image', () => {
fixture.detectChanges();
let tile = document.querySelector('.tile-block--icon');
let tile = document.querySelector('.tile-block-image');
expect(document.contains(tile)).toBeTruthy();
});

@ -5,6 +5,7 @@ export interface ITileViewEntry {
attribute:string;
icon:string;
description:string;
image:string;
}
@Component({

@ -0,0 +1,5 @@
<svg width="150" height="150" viewBox="0 0 150 150" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M28.5704 61.654C28.5704 68.4687 34.1064 74 40.9319 74C47.7574 74 53.2934 68.4687 53.2934 61.654C53.2934 54.8393 47.7574 49.3081 40.9319 49.3081C34.1064 49.3081 28.5704 54.8393 28.5704 61.654ZM40.9319 81.5608C38.7727 81.5608 36.6299 81.1416 34.637 80.4487H34.2512C26.3122 80.4487 19.6628 87.0921 19.6628 95.0189C19.6628 98.2056 22.2623 100.692 25.3435 100.692H48.8396V95.575C48.8396 90.3348 50.8177 85.6018 53.8473 81.9379C52.0039 80.9961 49.9017 80.4487 47.6126 80.4487H47.366C45.3691 81.1429 43.2229 81.5608 40.9319 81.5608Z" fill="#A0CDE0" stroke="#0A71B9" stroke-width="2"/>
<path d="M130.819 88.1941L119.918 77.2623C118.464 75.8047 116.526 74.9545 114.467 74.9545H104.777C102.718 74.9545 100.901 76.7764 100.901 78.8413V88.5585C100.901 90.6234 101.749 92.5669 103.203 94.0244L114.104 104.956C115.678 106.535 118.101 106.535 119.676 104.956L130.819 93.7815C132.394 92.2025 132.394 89.7732 130.819 88.1941ZM108.653 85.6434C107.079 85.6434 105.746 84.4287 105.746 82.7282C105.746 81.1492 107.079 79.813 108.653 79.813C110.349 79.813 111.56 81.1492 111.56 82.7282C111.56 84.4287 110.349 85.6434 108.653 85.6434Z" fill="#6DC391"/>
<path d="M81.6425 74.9545C90.1212 74.9545 97.1465 68.031 97.1465 59.4069C97.1465 50.9044 90.1212 43.8594 81.6425 43.8594C73.0427 43.8594 66.1386 50.9044 66.1386 59.4069C66.1386 68.031 73.0427 74.9545 81.6425 74.9545ZM97.0253 88.5585V79.5701C95.5718 79.2057 93.9972 78.8413 92.4226 78.8413H90.3635C87.6987 80.056 84.7918 80.7848 81.6425 80.7848C78.4933 80.7848 75.4652 80.056 72.8004 78.8413H70.7413C61.7781 78.8413 54.5107 86.2507 54.5107 95.2391V100.219C54.5107 103.499 57.0543 106.049 60.3246 106.049H102.96C104.777 106.049 106.473 105.199 107.442 103.742L100.417 96.6967C98.2366 94.5103 97.0253 91.5952 97.0253 88.5585Z" fill="#0A71B9"/>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@ -0,0 +1,17 @@
<svg width="150" height="150" viewBox="0 0 150 150" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18 25L51 25" stroke="#0A71B9" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M99 25L133 25" stroke="#6DC391" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M58 25L92 25" stroke="#A0CDE0" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<rect x="17" y="34" width="33" height="27" rx="7" stroke="#0A71B9" stroke-width="2"/>
<path d="M28 48H38" stroke="#0A71B9" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<rect x="99" y="34" width="32" height="27" rx="7" stroke="#6DC391" stroke-width="2"/>
<rect x="99" y="67" width="32" height="27" rx="7" stroke="#6DC391" stroke-width="2"/>
<path d="M110 48H120" stroke="#6DC391" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M110 81H120" stroke="#6DC391" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<rect x="58" y="34" width="33" height="27" rx="7" fill="#A0CDE0" stroke="#0A71B9" stroke-width="2"/>
<rect x="58" y="67" width="33" height="27" rx="7" fill="#A0CDE0" stroke="#0A71B9" stroke-width="2"/>
<rect x="58" y="100" width="33" height="27" rx="7" fill="#A0CDE0" stroke="#0A71B9" stroke-width="2"/>
<path d="M70 48H80" stroke="#0A71B9" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M70 81H80" stroke="#0A71B9" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M70 114H80" stroke="#0A71B9" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

@ -0,0 +1,14 @@
<svg width="150" height="150" viewBox="0 0 150 150" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="74" y="66" width="46" height="21" rx="8" stroke="#0A71B9" stroke-width="2"/>
<rect x="74" y="96" width="46" height="21" rx="8" stroke="#6DC391" stroke-width="2"/>
<path d="M37.0383 56L112.962 56C117.401 56 121 52.3842 121 47.924V41.0758C121 36.6156 117.401 33 112.962 33L37.0383 33C32.5988 33 29 36.6156 29 41.0758V47.924C29 52.3842 32.5988 56 37.0383 56Z" fill="#0A71B9" stroke="#0A71B9" stroke-width="2" stroke-miterlimit="10"/>
<path d="M42.2397 47.65C43.8524 47.65 45.1597 46.3428 45.1597 44.7301C45.1597 43.1174 43.8524 41.8101 42.2397 41.8101C40.6271 41.8101 39.3198 43.1174 39.3198 44.7301C39.3198 46.3428 40.6271 47.65 42.2397 47.65Z" fill="#A0CDE0"/>
<path d="M54.9897 44.73H107.86" stroke="#A0CDE0" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M42 62V107" stroke="#0A71B9" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M64 77H42" stroke="#0A71B9" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M64 107H42" stroke="#0A71B9" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M85.9199 79.84C87.5326 79.84 88.8398 78.5327 88.8398 76.92C88.8398 75.3074 87.5326 74 85.9199 74C84.3073 74 83 75.3074 83 76.92C83 78.5327 84.3073 79.84 85.9199 79.84Z" fill="#0A71B9"/>
<path d="M95 77H110" stroke="#0A71B9" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M85.9199 109.84C87.5326 109.84 88.8398 108.533 88.8398 106.92C88.8398 105.307 87.5326 104 85.9199 104C84.3073 104 83 105.307 83 106.92C83 108.533 84.3073 109.84 85.9199 109.84Z" fill="#6DC391"/>
<path d="M95 107H110" stroke="#6DC391" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@ -0,0 +1,12 @@
<svg width="150" height="150" viewBox="0 0 150 150" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="50.0286" cy="99.9714" r="20.0286" stroke="#A0CDE0" stroke-width="2"/>
<circle cx="99.9714" cy="50.0286" r="20.0286" stroke="#0A71B9" stroke-width="2"/>
<path d="M45 100H55" stroke="#A0CDE0" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M95.125 45.2917L104.612 54.7787" stroke="#0A71B9" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M104.708 45.2917L95.2213 54.7787" stroke="#0A71B9" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="50.0286" cy="50.0286" r="20.0286" fill="#6DC391" stroke="#6DC391" stroke-width="2"/>
<circle cx="99.9714" cy="99.9714" r="20.0286" fill="#7C7C7C" stroke="#7C7C7C" stroke-width="2"/>
<path d="M44.7043 49.3853C44.3122 48.9963 43.679 48.9988 43.2901 49.3909C42.9011 49.783 42.9036 50.4162 43.2957 50.8051L44.7043 49.3853ZM47.9361 54L47.2318 54.7099C47.6217 55.0967 48.2505 55.0967 48.6404 54.7099L47.9361 54ZM56.7043 46.7099C57.0964 46.3209 57.0989 45.6878 56.7099 45.2957C56.3209 44.9036 55.6878 44.9011 55.2957 45.2901L56.7043 46.7099ZM43.2957 50.8051L47.2318 54.7099L48.6404 53.2901L44.7043 49.3853L43.2957 50.8051ZM48.6404 54.7099L56.7043 46.7099L55.2957 45.2901L47.2318 53.2901L48.6404 54.7099Z" fill="white"/>
<path d="M99.9167 93.2083L99.9167 102.792" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="99.9167" cy="106.625" r="0.958333" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

@ -0,0 +1,18 @@
<svg width="150" height="150" viewBox="0 0 150 150" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="29" y="96" width="24" height="21" rx="8" fill="#A0CDE0" stroke="#0A71B9" stroke-width="2"/>
<path d="M40.9199 109.84C42.5326 109.84 43.8398 108.533 43.8398 106.92C43.8398 105.307 42.5326 104 40.9199 104C39.3073 104 38 105.307 38 106.92C38 108.533 39.3073 109.84 40.9199 109.84Z" fill="#0A71B9"/>
<rect x="52" y="64" width="44" height="21" rx="8" fill="#A0CDE0" stroke="#0A71B9" stroke-width="2"/>
<path d="M61.9199 77.84C63.5326 77.84 64.8398 76.5327 64.8398 74.92C64.8398 73.3074 63.5326 72 61.9199 72C60.3073 72 59 73.3074 59 74.92C59 76.5327 60.3073 77.84 61.9199 77.84Z" fill="#0A71B9"/>
<rect x="62" y="96" width="24" height="21" rx="8" stroke="#0A71B9" stroke-width="2"/>
<path d="M73.9199 109.84C75.5326 109.84 76.8398 108.533 76.8398 106.92C76.8398 105.307 75.5326 104 73.9199 104C72.3073 104 71 105.307 71 106.92C71 108.533 72.3073 109.84 73.9199 109.84Z" fill="#0A71B9"/>
<rect x="95" y="96" width="24" height="21" rx="8" stroke="#6DC391" stroke-width="2"/>
<path d="M106.92 109.84C108.533 109.84 109.84 108.533 109.84 106.92C109.84 105.307 108.533 104 106.92 104C105.307 104 104 105.307 104 106.92C104 108.533 105.307 109.84 106.92 109.84Z" fill="#6DC391"/>
<path d="M71 75H86" stroke="#0A71B9" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<rect x="52" y="32" width="44" height="21" rx="8" fill="#0A71B9" stroke="#0A71B9" stroke-width="2"/>
<path d="M61.9199 45.84C63.5326 45.84 64.8398 44.5327 64.8398 42.92C64.8398 41.3074 63.5326 40 61.9199 40C60.3073 40 59 41.3074 59 42.92C59 44.5327 60.3073 45.84 61.9199 45.84Z" fill="#A0CDE0"/>
<path d="M71 43H86" stroke="#A0CDE0" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M107 91V75C107 74.4477 106.552 74 106 74H100" stroke="#0A71B9" stroke-width="2" stroke-linecap="round"/>
<path d="M41 91V75C41 74.4477 41.4477 74 42 74H48" stroke="#0A71B9" stroke-width="2" stroke-linecap="round"/>
<path d="M74 92L74 89" stroke="#0A71B9" stroke-width="2" stroke-linecap="round"/>
<path d="M74 60L74 57" stroke="#0A71B9" stroke-width="2" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@ -0,0 +1,13 @@
<svg width="150" height="150" viewBox="0 0 150 150" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect y="1.12329" width="63.7498" height="28.9411" transform="matrix(0.827379 0.561644 -0.827379 0.561644 61.5294 47.4924)" fill="#A0CDE0" stroke="#0A71B9" stroke-width="2"/>
<rect x="-1.65476" y="-1.19209e-07" width="63.7498" height="28.9411" transform="matrix(-0.827379 0.561643 -0.827379 -0.561644 111.976 65.3072)" fill="#A0CDE0" stroke="#0A71B9" stroke-width="2"/>
<rect x="-1.65476" y="-1.19209e-07" width="28.9411" height="28.9411" transform="matrix(-0.827379 0.561643 -0.827379 -0.561644 97.5765 75.0823)" fill="white" stroke="#0A71B9" stroke-width="2"/>
<path d="M52.1428 93.8673L60.1429 98.3994L75.0002 89.3353V122.193L52.1428 108.597V93.8673Z" fill="#0A71B9"/>
<path d="M75.0002 89.3353L89.8575 98.3994L97.8575 93.8673V108.597L75.0002 122.193V89.3353Z" fill="#0A71B9"/>
<path d="M75 81L75 68" stroke="#0A71B9" stroke-width="2" stroke-linecap="round"/>
<line x1="75" y1="66.4142" x2="68.8737" y2="72.5405" stroke="#0A71B9" stroke-width="2" stroke-linecap="round"/>
<line x1="81.1261" y1="72.5405" x2="74.9998" y2="66.4142" stroke="#0A71B9" stroke-width="2" stroke-linecap="round"/>
<path d="M70.439 100.144V110.711H67.4626V102.786H67.3983L65 104.169V101.734L67.6981 100.144H70.439Z" fill="white"/>
<path d="M73.7876 110.876C73.3736 110.876 73.0185 110.737 72.7222 110.458C72.4296 110.176 72.2851 109.834 72.2886 109.432C72.2851 109.039 72.4296 108.704 72.7222 108.425C73.0185 108.147 73.3736 108.008 73.7876 108.008C74.1801 108.008 74.5263 108.147 74.8261 108.425C75.1295 108.704 75.2829 109.039 75.2865 109.432C75.2829 109.7 75.2098 109.944 75.067 110.164C74.9278 110.381 74.7458 110.555 74.521 110.685C74.2961 110.813 74.0517 110.876 73.7876 110.876Z" fill="white"/>
<path d="M81.1605 111C80.1648 110.997 79.3047 110.775 78.5802 110.334C77.8557 109.894 77.2971 109.26 76.9046 108.431C76.512 107.602 76.3175 106.608 76.321 105.448C76.3246 104.286 76.5209 103.299 76.9099 102.487C77.3025 101.675 77.8593 101.058 78.5802 100.635C79.3047 100.212 80.1648 100 81.1605 100C82.1562 100 83.0163 100.213 83.7408 100.64C84.4653 101.063 85.0239 101.68 85.4164 102.492C85.809 103.304 86.0035 104.289 86 105.448C86 106.614 85.8037 107.612 85.4111 108.441C85.0185 109.27 84.46 109.904 83.7355 110.345C83.0146 110.782 82.1562 111 81.1605 111ZM81.1605 108.668C81.6744 108.668 82.0956 108.41 82.4239 107.894C82.7558 107.375 82.92 106.559 82.9164 105.448C82.9164 104.723 82.8415 104.129 82.6916 103.668C82.5417 103.207 82.3347 102.867 82.0706 102.647C81.8065 102.423 81.5031 102.311 81.1605 102.311C80.6466 102.311 80.2272 102.563 79.9025 103.065C79.5777 103.567 79.4117 104.361 79.4046 105.448C79.401 106.188 79.4742 106.797 79.6241 107.275C79.774 107.75 79.981 108.1 80.2451 108.327C80.5127 108.554 80.8179 108.668 81.1605 108.668Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

@ -36,28 +36,36 @@ en:
click_to_remove_list: "Click to remove this list"
board_type:
text: 'Board type'
free: 'Basic board'
free: 'basic'
select_board_type: 'Please choose the type of board you need.'
free_text: >
A board in which you can freely create lists and order your work packages within.
Dragging work packages between lists do not change the work package itself.
Start from scratch with a blank board.
Manually add cards and columns to this board.
action: 'Action board'
action_by_attribute: 'Action board (%{attribute})'
action_text: >
A board with filtered lists on %{attribute} attribute. Moving work packages to other lists
will update their attribute.
action_text_subprojects: >
A board with lists of subprojects of this project and their work packages as list items.
Dragging work packages to other lists will move them to the corresponding subproject.
Board with automated columns for subprojects.
Ideal for handling permissions across stakeholders.
action_text_subtasks: >
A board with lists of selected parents and their child work packages as list items.
Dragging work packages to other lists will update the parent accordingly.
Board with automated columns for sub-elements.
Dragging work packages to other lists updates the parent accordingly.
action_text_status: >
Basic kanban style board with columns for status such as To Do, In Progress, Done.
action_text_assignee: >
Board with automated columns based on assigned users.
Ideal for dispatching work packages.
action_text_version: >
Board with automated columns based on the version attribute.
Ideal for planning software releases.
action_type:
assignee: assignee
status: status
version: version
subproject: subproject
subtasks: children
subtasks: Parent_child
select_attribute: "Action attribute"
add_list_modal:

@ -63,7 +63,7 @@ describe 'Subtasks action board', type: :feature, js: true do
board_index.visit!
# Create new board
board_page = board_index.create_board action: :Children, expect_empty: true
board_page = board_index.create_board action: :Parent_child, expect_empty: true
# Expect we can add a work package column
board_page.add_list option: 'Parent WP'
@ -87,7 +87,7 @@ describe 'Subtasks action board', type: :feature, js: true do
board_index.visit!
# Create new board
board_page = board_index.create_board action: :Children, expect_empty: true
board_page = board_index.create_board action: :Parent_child, expect_empty: true
# Expect we can add a child 1
board_page.add_list option: 'Parent WP'
@ -100,7 +100,7 @@ describe 'Subtasks action board', type: :feature, js: true do
board_page.expect_movable 'Parent WP', 'Child', movable: true
board_page.board(reload: true) do |board|
expect(board.name).to eq 'Action board (children)'
expect(board.name).to eq 'Action board (Parent_child)'
queries = board.contained_queries
expect(queries.count).to eq(1)
@ -158,7 +158,7 @@ describe 'Subtasks action board', type: :feature, js: true do
it 'prevents adding a work package to its own column' do
board_index.visit!
board_page = board_index.create_board action: :Children, expect_empty: true
board_page = board_index.create_board action: :Parent_child, expect_empty: true
board_page.add_list option: 'Parent WP'
board_page.expect_list 'Parent WP'
board_page.expect_card 'Parent WP', 'Child'

@ -60,9 +60,9 @@ module Pages
page.find('.toolbar-item a', text: 'Board').click
if action == nil
find('.tile-block', text: 'Basic Board').click
find('.tile-block-title', text: 'Basic').click
else
find('.tile-block', text: "Action Board (#{action.to_s})").click
find('.tile-block-title', text: action.to_s).click
end
if expect_empty

Loading…
Cancel
Save