Skip to content

Commit

Permalink
Fix file issues
Browse files Browse the repository at this point in the history
 - Fix camera takes wrong width and height properties
 - Fix imageHeight/imageWidth behaviour for multiple preview
 - Fix actions are not visible in design mode
 - Fix choose button is not clickable
 - Fix empty space under image on mobile
  • Loading branch information
dk981234 committed Oct 30, 2023
1 parent 283fe5e commit a83bf28
Show file tree
Hide file tree
Showing 52 changed files with 343 additions and 112 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<ng-template #template>
<div *ngIf="!question.isReadOnly" role="button" tabindex="0" [class]="question.getChooseFileCss()"
<label *ngIf="!question.isReadOnly" tabindex="0" [class]="question.getChooseFileCss()"
[attr.for]="question.inputId" [attr.aria-label]="question.chooseButtonText" [key2click]>
<svg *ngIf="question.cssClasses.chooseFileIconId" [title]="question.chooseButtonText"
[iconName]="question.cssClasses.chooseFileIconId" [size]="'auto'" sv-ng-svg-icon></svg>
<span>{{ question.chooseButtonText }}</span>
</div>
</label>
</ng-template>
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
val.name
}}</a>
</div>
<div [class]="question.cssClasses.imageWrapper">
<div [class]="question.getImageWrapperCss(val)">
<img *ngIf="question.canPreviewImage(val)" [attr.src]="val.content | safeUrl"
[style.height]="question.imageHeight" [style.width]="question.imageWidth" alt="File preview" />
<svg *ngIf="question.defaultImage(val)" [iconName]="question.cssClasses.defaultImageIconId"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<template>
<div
<label
v-if="!question.isReadOnly"
role="button"
tabindex="0"
:class="question.getChooseFileCss()"
:for="question.inputId"
Expand All @@ -15,7 +14,7 @@
:size="'auto'"
></sv-svg-icon>
<span>{{ question.chooseButtonText }}</span>
</div>
</label>
</template>
<script setup lang="ts">
import type { QuestionFileModel, Action } from "survey-core";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
>{{ val.name }}</a
>
</div>
<div :class="question.cssClasses.imageWrapper">
<div :class="question.getImageWrapperCss(val)">
<img
v-if="question.canPreviewImage(val)"
:src="val.content"
Expand Down
4 changes: 4 additions & 0 deletions src/actions/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export interface IAction {
* @see visible
*/
enabled?: boolean;
enabledIf?: () => boolean;
/**
* Specifies the visibility of the action item's title.
* @see title
Expand Down Expand Up @@ -441,10 +442,13 @@ export class Action extends BaseAction implements IAction, ILocalizableOwner {
public getVisible(): boolean {
return this._visible;
}

public enabledIf?: () => boolean;
public setEnabled(val: boolean): void {
this._enabled = val;
}
public getEnabled(): boolean {
if(this.enabledIf) return this.enabledIf();
return this._enabled;
}
public setComponent(val: string): void {
Expand Down
1 change: 1 addition & 0 deletions src/defaultCss/defaultV2Css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,7 @@ export var defaultV2Css = {
removeFileButton: "sd-context-btn--negative sd-file__remove-file-button",
dragAreaPlaceholder: "sd-file__drag-area-placeholder",
imageWrapper: "sd-file__image-wrapper",
imageWrapperDefaultImage: "sd-file__image-wrapper--default-image",
single: "sd-file--single",
singleImage: "sd-file--single-image",
mobile: "sd-file--mobile",
Expand Down
4 changes: 4 additions & 0 deletions src/defaultV2-theme/blocks/sd-action.scss
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ svg.sd-action--icon {
cursor: default;
opacity: 0.25;
pointer-events: none;

use {
fill: $font-questiondescription-color;
}
}

.sd-action:not(.sd-action--pressed):hover,
Expand Down
38 changes: 27 additions & 11 deletions src/defaultV2-theme/blocks/sd-file.scss
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,10 @@
.sd-file__preview {
position: relative;
display: flex;
align-items: center;
align-items: stretch;
flex-direction: column;
min-height: 100%;
width: calcSize(12);
margin: 0;

.sd-file__default-image {
Expand Down Expand Up @@ -182,6 +183,8 @@
white-space: normal;
word-break: break-all;
width: calcSize(12);
min-width: 100%;
max-width: 100%;
overflow: hidden;
max-height: calcSize(6);
text-overflow: ellipsis;
Expand All @@ -203,30 +206,34 @@
.sd-file__image-wrapper {
position: relative;
text-align: center;
min-width: calcSize(12);
display: flex;
align-items: center;
justify-content: center;
width: calcSize(12);
min-height: calcSize(12);
height: calcSize(12);
background: $background-dim;

img:not(.sd-file__default-image) {
display: block;
max-width: 100%;
max-height: 100%;
width: calcSize(12);
height: calcSize(12);
object-fit: contain;
background: $background-dim;
}
}

.sd-file__image-wrapper--default-image {
background: transparent;
}

.sd-file--single {
img:hover+.sd-file__remove-file-button {
display: none;
}
}

.sd-file--mobile:first-child {
.sd-file__list {
height: calc(100% - 4 * #{$base-unit});
}
}

.sd-file--single-image {
height: calc(36 * #{$base-unit});

Expand All @@ -244,14 +251,17 @@
width: 100%;
}

.sd-file__image-wrapper {
background-color: $background-dim-light;
}

.sd-file__image-wrapper {
min-height: 100%;
min-width: 100%;

img {
width: 100%;
height: 100%;
background-color: $background-dim-light;
}
}

Expand All @@ -264,12 +274,18 @@
a {
color: transparent;
width: 100%;
min-width: 100%;
max-width: 100%;
height: 100%;
outline: none;
}
}
}

.sd-file__image-wrapper.sd-file__image-wrapper--default-image {
background: transparent;
}

.sd-file>input:focus+.sd-file__decorator .sd-file__choose-btn {
&.sd-file__choose-btn--icon {
use {
Expand Down Expand Up @@ -326,7 +342,7 @@
}

.sd-file__video-container {
background-color: $background-dim;
background-color: $background-dark;
position: absolute;
top: 0;
left: 0;
Expand Down
4 changes: 2 additions & 2 deletions src/knockout/components/file/choose-file.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div tabindex="0" role="button" data-bind="css: question.koChooseFileCss, key2click, attr: { for: question.inputId, 'aria-label': question.koGetChooseButtonText() }">
<label tabindex="0" data-bind="css: question.koChooseFileCss, key2click, attr: { for: question.inputId, 'aria-label': question.koGetChooseButtonText() }">
<!-- ko if: question.cssClasses.chooseFileIconId -->
<!-- ko component: { name: 'sv-svg-icon', params: { title: question.koGetChooseButtonText(), iconName: question.cssClasses.chooseFileIconId, size: 'auto' } } --><!-- /ko -->
<!-- /ko -->
<span data-bind="text: question.koGetChooseButtonText()"></span>
</div>
</label>
2 changes: 1 addition & 1 deletion src/knockout/components/file/file-preview.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<div data-bind="css: question.cssClasses.fileList, foreach: question.koData, visible: question.koHasValue">
<span data-bind="visible: question.isPreviewVisible($index()), css: question.cssClasses.preview">
<!-- ko template: { name: 'survey-question-file-sign', data: {question: question, item: $data, fileSignCss: question.cssClasses.fileSign} } --><!-- /ko -->
<div data-bind="css: question.cssClasses.imageWrapper">
<div data-bind="css: question.getImageWrapperCss($data)">
<!-- ko if: question.canPreviewImage($data) -->
<img data-bind="attr: { src: $data.content }, style : { height: question.imageHeight, width: question.imageWidth }" alt="File preview">
<!-- /ko -->
Expand Down
26 changes: 16 additions & 10 deletions src/question_file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { Helpers } from "./helpers";
import { Camera } from "./utils/camera";
import { LocalizableString } from "./localizablestring";
import { settings } from "./settings";
import { getRenderedSize } from "./utils/utils";

/**
* A class that describes the File Upload question type.
Expand Down Expand Up @@ -92,8 +93,7 @@ export class QuestionFileModel extends Question {
const isUploading = this.isUploading;
const isPlayingVideo = this.isPlayingVideo;
const isDefaultV2Theme = this.isDefaultV2Theme;
const isReadOnly = this.isInputReadOnly;
return !isUploading && !isPlayingVideo && !isReadOnly && isDefaultV2Theme;
return !isUploading && !isPlayingVideo && isDefaultV2Theme;
}

constructor(name: string) {
Expand Down Expand Up @@ -162,6 +162,7 @@ export class QuestionFileModel extends Question {
iconSize: "auto",
title: <string>(new ComputedUpdater<string>(() => this.takePhotoCaption) as any),
showTitle: <boolean>(new ComputedUpdater<boolean>(() => !this.isAnswered) as any),
enabledIf: () => !this.isInputReadOnly,
action: () => {
this.startVideo();
}
Expand All @@ -172,6 +173,7 @@ export class QuestionFileModel extends Question {
iconSize: "auto",
title: <string>(new ComputedUpdater<string>(() => this.clearButtonCaption) as any),
showTitle: false,
enabledIf: () => !this.isInputReadOnly,
innerCss: <string>(new ComputedUpdater<string>(() => this.cssClasses.removeButton) as any),
action: () => {
this.doClean();
Expand All @@ -180,10 +182,9 @@ export class QuestionFileModel extends Question {
[this.closeCameraAction, this.changeCameraAction, this.takePictureAction].forEach((action) => {
action.cssClasses = {};
});
this.registerFunctionOnPropertiesValueChanged(["currentMode", "isAnswered"], () => {
this.updateActions();
this.registerFunctionOnPropertiesValueChanged(["sourceType", "currentMode", "isAnswered"], () => {
this.updateActionsVisibility();
});
this.updateActions();
this.actionsContainer.actions = [this.chooseFileAction, this.startCameraAction, this.cleanAction];
this.fileNavigator.actions = [this.prevFileAction, this.fileIndexAction, this.nextFileAction];
}
Expand All @@ -198,13 +199,14 @@ export class QuestionFileModel extends Question {
this.startVideoInCamera();
}, 0);
}

private startVideoInCamera(): void {
this.camera.startVideo(this.videoId, (stream: MediaStream) => {
this.videoStream = stream;
if(!stream) {
this.stopVideo();
}
}, this.imageWidth, this.imageHeight);
}, getRenderedSize(this.imageWidth), getRenderedSize(this.imageHeight));
}
public stopVideo(): void {
this.setIsPlayingVideo(false);
Expand Down Expand Up @@ -480,9 +482,10 @@ export class QuestionFileModel extends Question {
}
}
}
private updateActions() {
this.chooseFileAction.visible = this.hasFileUI;
this.startCameraAction.visible = this.hasVideoUI;
private updateActionsVisibility() {
const isDesignMode = this.isDesignMode;
this.chooseFileAction.visible = (!isDesignMode && this.hasFileUI) || (isDesignMode && this.sourceType !== "camera");
this.startCameraAction.visible = (!isDesignMode && this.hasVideoUI) || (isDesignMode && this.sourceType !== "file");
this.cleanAction.visible = !!this.isAnswered;
}
get inputTitle(): string {
Expand Down Expand Up @@ -778,6 +781,9 @@ export class QuestionFileModel extends Question {
}
return questionPlainData;
}
public getImageWrapperCss(data: any): string {
return new CssClassBuilder().append(this.cssClasses.imageWrapper).append(this.cssClasses.imageWrapperDefaultImage, this.defaultImage(data)).toString();
}
protected getActionsContainerCss(css: any): string {
return new CssClassBuilder()
.append(css.actionsContainer)
Expand Down Expand Up @@ -862,7 +868,7 @@ export class QuestionFileModel extends Question {
endLoadingFromJson(): void {
super.endLoadingFromJson();
this.updateCurrentMode();
this.updateActions();
this.updateActionsVisibility();
this.loadPreview(this.value);
}
protected needResponsiveness(): boolean {
Expand Down
5 changes: 2 additions & 3 deletions src/react/components/file/file-choose-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,15 @@ export class SurveyFileChooseButton extends ReactSurveyElement {
}
render() {
return attachKey2click(
<div
role="button"
<label
tabIndex={0}
className={this.question.getChooseFileCss()}
// htmlFor={this.question.inputId}
aria-label={this.question.chooseButtonText}
>
{(!!this.question.cssClasses.chooseFileIconId) ? <SvgIcon title={this.question.chooseButtonText} iconName={this.question.cssClasses.chooseFileIconId} size={"auto"}></SvgIcon>: null }
<span>{this.question.chooseButtonText}</span>
</div>
</label>
);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/react/components/file/file-preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export class SurveyFilePreview extends SurveyElementBase<{ question: QuestionFil
style={{ display: this.question.isPreviewVisible(index) ? undefined : "none" }}
>
{this.renderFileSign(this.question.cssClasses.fileSign, val)}
<div className={this.question.cssClasses.imageWrapper}>
<div className={this.question.getImageWrapperCss(val)}>
{this.question.canPreviewImage(val) ? (
<img
src={val.content}
Expand Down

0 comments on commit a83bf28

Please sign in to comment.