Skip to content

Commit

Permalink
Merge pull request #9 from rajnishdargan/asq-feature
Browse files Browse the repository at this point in the history
Issue #223093 feat: Arrange Sequence Question Implementation
  • Loading branch information
vaivk369 authored Aug 23, 2024
2 parents 229c986 + 56c0336 commit bdc7f32
Show file tree
Hide file tree
Showing 20 changed files with 693 additions and 145 deletions.
2 changes: 1 addition & 1 deletion projects/quml-library/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tekdi/sunbird-quml-player",
"version": "9.0.0-beta.8",
"version": "9.0.0-beta.9",
"schematics": "./schematics/collection.json",
"ng-add": {
"save": "dependencies"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<ng-container *ngIf="optionsShuffled && (layout === 'VERTICAL' || layout === 'DEFAULT')">
<div id="dragdropSpace" cdkDropList [cdkDropListData]="shuffledOptions" class="asq-horizontal-list" (cdkDropListDropped)="onDrop($event)">
<div class="asq-horizontal-box" *ngFor="let option of shuffledOptions" cdkDrag cdkDragBoundary="#dragdropSpace">
<div [innerHTML]="option.label"></div>
<quml-reorder></quml-reorder>
</div>
</div>
</ng-container>
<ng-container *ngIf="optionsShuffled && (layout === 'HORIZONTAL')">
<div id="dragdropSpace" cdkDropList cdkDropListOrientation="horizontal" [cdkDropListData]="shuffledOptions" class="horizontal-list" (cdkDropListDropped)="onDrop($event)">
<div class="asq-vertical-box" *ngFor="let option of shuffledOptions" cdkDrag cdkDragBoundary="#dragdropSpace">
<div class="drag-handle">
<quml-reorder></quml-reorder>
</div>
<div [innerHTML]="option.label"></div>
</div>
</div>
</ng-container>
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
.asq-horizontal-box{
display: flex;
align-items: center;
justify-content: space-between;
margin: 15px;
border:1px solid #b3a8a869;
cursor: move;
box-shadow: rgba(17, 17, 26, 0.1) 0px 4px 16px, rgba(17, 17, 26, 0.05) 0px 8px 32px;
padding: 15px 20px;
border-radius: 6px;
}
::ng-deep .asq-horizontal-box p{
margin-top: 5px;
margin-bottom: 5px;
}
.cdk-drag-preview {
box-sizing: border-box;
border-radius: 4px;
box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2),
0 8px 10px 1px rgba(0, 0, 0, 0.14),
0 3px 14px 2px rgba(0, 0, 0, 0.12);
}
.cdk-drag-placeholder {
opacity: 0;
}

.cdk-drag-animating {
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}

.cdk-drop-list-dragging .asq-horizontal-box:not(.cdk-drag-placeholder) {
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}
::ng-deep .asq-horizontal-box img
{
width: 70px;
height: 70px;
object-fit: contain;
}
//horizontal layout css
.horizontal-list {
display: flex;
justify-content: space-between;
flex-wrap: nowrap;
width: 100%;
padding: 10px;
box-sizing: border-box;
}

.asq-vertical-box {
flex: 0 1 25%;
max-width: 25%;
position:relative;
padding: 0px 15px;
border: solid 1px #ccccccab;
color: rgba(0, 0, 0, 0.87);
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
cursor: move;
background: white;
margin:10px;
border-radius: 4px;
min-height:150px;
margin-top:2%;
box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
}
::ng-deep .asq-vertical-box img
{
width: 70px;
height: 70px;
object-fit: contain;
}
::ng-deep .asq-vertical-box p{
line-height: 20px;
margin-top: 5px;
margin-bottom: 5px;
}

.horizontal-list.cdk-drop-list-dragging .asq-vertical-box:not(.cdk-drag-placeholder) {
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}
.centered-align{
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
}
.drag-handle{
position: absolute;
top: 5px;
right: 5px;
cursor: move;
}
@media screen and (max-width: 600px) {
::ng-deep .asq-vertical-box p {
line-height: 14px;
margin-top: 5px;
margin-bottom: 5px;
font-size: 10px;
padding: 7px;
}
.asq-vertical-box{
margin: 0% 1px 10px;
padding:0px;
}
.horizontal-list{
padding:0px;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { AsqOptionsComponent } from './asq-options.component';

describe('AsqOptionsComponent', () => {
let component: AsqOptionsComponent;
let fixture: ComponentFixture<AsqOptionsComponent>;

beforeEach(() => {
TestBed.configureTestingModule({
declarations: [AsqOptionsComponent]
});
fixture = TestBed.createComponent(AsqOptionsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { Component, Input, Output, OnInit, OnChanges, SimpleChanges, EventEmitter } from '@angular/core';
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
import { AsqOptions } from '../../interfaces/asq-interface';
import * as _ from 'lodash-es';

@Component({
selector: 'quml-asq-options',
templateUrl: './asq-options.component.html',
styleUrls: ['./asq-options.component.scss'],
})
export class AsqOptionsComponent implements OnInit, OnChanges {
@Input() options: any[];
@Input() layout: string;
@Input() shuffleOptions: boolean;
@Input() replayed: boolean;
@Input() tryAgain?: boolean;
@Output() reorderedOptions = new EventEmitter<AsqOptions[]>();
shuffledOptions: any[];
optionsShuffled = false;
isModalVisible: boolean = false;
selectedImageSrc: string = '';

constructor() {
this.shuffledOptions = [];
}

ngOnInit() {
this.shuffleMTFOptions();

}

ngOnChanges(): void {
if(this.replayed || this.tryAgain) {
this.shuffleMTFOptions();
}
}

shuffleMTFOptions() {
// Shuffle the options
this.shuffledOptions = _.shuffle(this.options);
this.optionsShuffled = true;

// Ensure no item retains its original position
let isSameAsOriginal = this.shuffledOptions.some((item, index) => item.value === this.options[index].value);
while (isSameAsOriginal) {
this.shuffledOptions = _.shuffle(this.options);
isSameAsOriginal = this.shuffledOptions.some((item, index) => item.value === this.options[index].value);
}
}

onDrop(event: CdkDragDrop<any[]>) {
moveItemInArray(this.shuffledOptions, event.previousIndex, event.currentIndex);
this.reorderedOptions.emit(this.shuffledOptions);
}

swapOptions(index1: number, index2: number) {
[this.shuffledOptions[index1], this.shuffledOptions[index2]] = [
this.shuffledOptions[index2],
this.shuffledOptions[index1],
];
}
}
9 changes: 9 additions & 0 deletions projects/quml-library/src/lib/asq/asq.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<div *ngIf="questionBody" class="question-body">
<div class="mtf-title">
<p [innerHTML]="questionBody"></p>
</div>
<quml-asq-options [shuffleOptions]="shuffleOptions" [replayed]="replayed" [tryAgain]="tryAgain" *ngIf="interactions?.response1?.options"
[options]="interactions.response1.options" (reorderedOptions)="handleReorderedOptions($event)" [layout]="layout">
</quml-asq-options>
</div>

Empty file.
21 changes: 21 additions & 0 deletions projects/quml-library/src/lib/asq/asq.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { AsqComponent } from './asq.component';

describe('AsqComponent', () => {
let component: AsqComponent;
let fixture: ComponentFixture<AsqComponent>;

beforeEach(() => {
TestBed.configureTestingModule({
declarations: [AsqComponent]
});
fixture = TestBed.createComponent(AsqComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
44 changes: 44 additions & 0 deletions projects/quml-library/src/lib/asq/asq.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Component,Input,Output,EventEmitter} from '@angular/core';
import {AsqOptions,AsqInteractions} from '../interfaces/asq-interface';

@Component({
selector: 'quml-asq',
templateUrl: './asq.component.html'
})
export class AsqComponent {
@Input() question?: any;
@Input() shuffleOptions: boolean;
@Input() replayed: boolean;
@Input() tryAgain?: boolean;
@Output() optionsReordered = new EventEmitter<AsqOptions>();

public interactions?: AsqInteractions;
public questionBody?: string;
public layout: 'VERTICAL' | 'HORIZONTAL' | 'DEFAULT';

ngOnInit(): void {
this.initialize();
}

initialize(): void {
this.setLayout();
this.interactions = this.question?.interactions;
this.questionBody = this.question?.body;
}

setLayout(): void {
const templateId = this.question?.templateId;
if (templateId === 'asq-vertical') {
this.layout = 'VERTICAL';
} else if (templateId === 'asq-horizontal') {
this.layout = 'HORIZONTAL';
} else {
console.error('Invalid or undefined templateId');
this.layout = 'DEFAULT';
}
}

handleReorderedOptions(reorderedOptions: AsqOptions) {
this.optionsReordered.emit(reorderedOptions);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<svg width="1em" height="1em" viewBox="0 0 320 512" xmlns="http://www.w3.org/2000/svg" fill="currentColor">
<path
d="M96 96c26.5 0 48-21.5 48-48S122.5 0 96 0 48 21.5 48 48s21.5 48 48 48zm128 0c26.5 0 48-21.5 48-48S250.5 0 224 0s-48 21.5-48 48 21.5 48 48 48zm-128 128c26.5 0 48-21.5 48-48s-21.5-48-48-48-48 21.5-48 48 21.5 48 48 48zm128 0c26.5 0 48-21.5 48-48s-21.5-48-48-48-48 21.5-48 48 21.5 48 48 48zm-128 128c26.5 0 48-21.5 48-48s-21.5-48-48-48-48 21.5-48 48 21.5 48 48 48zm128 0c26.5 0 48-21.5 48-48s-21.5-48-48-48-48 21.5-48 48 21.5 48 48 48zm-128 128c26.5 0 48-21.5 48-48s-21.5-48-48-48-48 21.5-48 48 21.5 48 48 48zm128 0c26.5 0 48-21.5 48-48s-21.5-48-48-48-48 21.5-48 48 21.5 48 48 48z" />
</svg>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { ReorderComponent } from './reorder.component';

describe('ReorderComponent', () => {
let component: ReorderComponent;
let fixture: ComponentFixture<ReorderComponent>;

beforeEach(() => {
TestBed.configureTestingModule({
declarations: [ReorderComponent]
});
fixture = TestBed.createComponent(ReorderComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Component } from '@angular/core';

@Component({
selector: 'quml-reorder',
templateUrl: './reorder.component.html'
})
export class ReorderComponent {

}
18 changes: 18 additions & 0 deletions projects/quml-library/src/lib/interfaces/asq-interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export interface AsqOptions {
label: string;
value: number;
}

export interface AsqValidation {
required: string;
}

export interface AsqResponse {
type: string;
options: AsqOptions [];
validation: AsqValidation;
}

export interface AsqInteractions {
response1: AsqResponse;
}
9 changes: 7 additions & 2 deletions projects/quml-library/src/lib/quml-library.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ import { MtfComponent } from './mtf/mtf.component';
import { MtfOptionsComponent } from './mtf/mtf-options/mtf-options.component';
import { DragDropModule } from "@angular/cdk/drag-drop"
import { CheckFigureDirective } from './mtf/check-figure.directive';
import { AsqComponent } from './asq/asq.component';
import { AsqOptionsComponent } from './asq/asq-options/asq-options.component';
import { ReorderComponent } from './icon/reorder/reorder.component';
@NgModule({
declarations: [
QumlLibraryComponent,
Expand Down Expand Up @@ -81,8 +84,10 @@ import { CheckFigureDirective } from './mtf/check-figure.directive';
ProgressIndicatorsComponent,
MtfComponent,
MtfOptionsComponent,
CheckFigureDirective

CheckFigureDirective,
AsqComponent,
AsqOptionsComponent,
ReorderComponent
],
imports: [
CommonModule,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@
<quml-mtf [shuffleOptions]='shuffleOptions' [question]='question' [replayed]="parentConfig?.isReplayed"
(optionsReordered)="handleMTFOptionsChange($event)" [tryAgain]="tryAgainClicked"></quml-mtf>
</div>
<div *ngIf="question?.primaryCategory.toLowerCase() === 'arrange sequence question'" class="mtf">
<quml-asq [shuffleOptions]='shuffleOptions' [question]='question' [replayed]="parentConfig?.isReplayed"
(optionsReordered)="handleASQOptionsChange($event)" [tryAgain]="tryAgainClicked"></quml-asq>
</div>
</div>
</slide>
</carousel>
Expand Down
Loading

0 comments on commit bdc7f32

Please sign in to comment.