Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Teacher Tool: Block Picker #9936

Merged
merged 59 commits into from
Mar 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
0b5a49a
Add ability to get an image uri from a block type using the iframe
thsparks Mar 15, 2024
52f6610
Add GetBlocksInfo request
thsparks Mar 18, 2024
24865ae
First pass at loading iframe even without a project, not sure if it's…
thsparks Mar 18, 2024
5268f00
Debug block picking & displaying
thsparks Mar 18, 2024
dfca3b3
Load all blocks into state
thsparks Mar 18, 2024
ad203fa
Block picker modal base, button to add
thsparks Mar 19, 2024
30e28f5
Working on block picker modal...
thsparks Mar 19, 2024
24591d8
Remove debug code
thsparks Mar 19, 2024
55f50a7
Change how we get categories
thsparks Mar 19, 2024
207071b
Remove unused getBlocksInfo
thsparks Mar 19, 2024
ac3ff69
Some styling
thsparks Mar 20, 2024
797fbbd
More styling
thsparks Mar 20, 2024
c686b78
Use custom expansion
thsparks Mar 20, 2024
57e534d
More styling
thsparks Mar 20, 2024
ee9f912
Connect modal and parameter value
thsparks Mar 20, 2024
1ba05cd
Fix rendering xml that doesn't have surrounding <xml> tags
thsparks Mar 20, 2024
b82a0dc
Get advanced and non-advanced categories
thsparks Mar 20, 2024
aaa25bf
Load blocks when frame loads, adjust styling
thsparks Mar 20, 2024
359d8af
Update criteria block displays when toolbox categories load
thsparks Mar 20, 2024
350cc76
loadAllBlocks -> loadToolboxCategories
thsparks Mar 20, 2024
8fa8eef
Better rename
thsparks Mar 20, 2024
afc457b
Use block tooltip when possible
thsparks Mar 20, 2024
5cd4825
Remove duplicate block ids
thsparks Mar 20, 2024
f3afe6a
Prettier
thsparks Mar 20, 2024
c9e68b9
Lock height
thsparks Mar 21, 2024
13df287
Escape block id string. Surprisingly, there are some with quotes in t…
thsparks Mar 21, 2024
221d6a1
Add to do
thsparks Mar 21, 2024
a2caacf
Use spread operator to simplify conversion
thsparks Mar 21, 2024
aa05ede
When we don't have blockXml, use existing createToolboxBlock to gener…
thsparks Mar 21, 2024
55fc40b
Remove unused escapeForXml code
thsparks Mar 21, 2024
2bee531
Use a var for the category colors
thsparks Mar 21, 2024
ee10cef
Hide iframe when project has not been set
thsparks Mar 21, 2024
4113767
Aria roles
thsparks Mar 21, 2024
16c6185
Remove a few to dos that are no longer necessary
thsparks Mar 21, 2024
0f39a18
Fix block display issues caused by display:none. It seemed to break h…
thsparks Mar 22, 2024
92756b0
Reload blocks when the editorcontentloaded event fires.
thsparks Mar 22, 2024
4b9781d
Remove unused useEffect import.
thsparks Mar 22, 2024
130c5c1
Add optional loading element for lazy image to replace spinner
thsparks Mar 22, 2024
1497d9f
React common build gulp export
thsparks Mar 22, 2024
a4f339d
Remove unnecessary style
thsparks Mar 22, 2024
438a420
Remove test code
thsparks Mar 22, 2024
0b89be7
Undo styling-only changes
thsparks Mar 22, 2024
df6d197
Prettier
thsparks Mar 22, 2024
c6b44a5
Undo style only change
thsparks Mar 22, 2024
9929a92
Style & comments
thsparks Mar 22, 2024
ab0b8cb
Merge branch 'master' of https://github.com/microsoft/pxt into thspar…
thsparks Mar 22, 2024
d8da579
Constant strings
thsparks Mar 22, 2024
59faeee
Merge branch 'master' of https://github.com/microsoft/pxt into thspar…
thsparks Mar 25, 2024
d7b8275
Fix padding on the right
thsparks Mar 25, 2024
5cb8e04
Add key props
thsparks Mar 26, 2024
0b67a33
Use find to lookup block in category
thsparks Mar 26, 2024
ae49127
Use rem not em for fonts
thsparks Mar 26, 2024
2fbadff
loadToolboxCategoriesAsync PR feedback
thsparks Mar 26, 2024
be091a3
Async in getToolboxCategories function name
thsparks Mar 26, 2024
b812e25
Update comments around loadToolboxCategoriesAsync to clarify we're in…
thsparks Mar 26, 2024
bf18f57
Combine modal options
thsparks Mar 26, 2024
a97eace
Prettier
thsparks Mar 26, 2024
fcb60ba
Remove modal from state, only use ModalOptions instead
thsparks Mar 26, 2024
713c29a
Prettier
thsparks Mar 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,7 @@ exports.tt = teacherTool;
exports.icons = buildSVGIcons;
exports.testhelpers = testhelpers;
exports.testpxteditor = testpxteditor;
exports.reactCommon = reactCommon;
exports.cli = gulp.series(
gulp.parallel(pxtlib, pxtweb),
gulp.parallel(pxtcompiler, pxtsim, backendutils),
Expand Down
42 changes: 41 additions & 1 deletion localtypings/pxteditor.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ declare namespace pxt.editor {
| "redo"
| "renderblocks"
| "renderpython"
| "renderxml"
| "renderbyblockid"
| "setscale"
| "startactivity"
| "saveproject"
Expand All @@ -64,6 +66,7 @@ declare namespace pxt.editor {
| "requestprojectcloudstatus"
| "convertcloudprojectstolocal"
| "setlanguagerestriction"
| "gettoolboxcategories"

| "toggletrace" // EditorMessageToggleTraceRequest
| "togglehighcontrast"
Expand Down Expand Up @@ -294,6 +297,21 @@ declare namespace pxt.editor {
layout?: BlockLayout;
}

export interface EditorMessageRenderXmlRequest extends EditorMessageRequest {
action: "renderxml";
// xml to render
xml: string;
snippetMode?: boolean;
layout?: BlockLayout;
}

export interface EditorMessageRenderByBlockIdRequest extends EditorMessageRequest {
action: "renderbyblockid";
blockId: string;
snippetMode?: boolean;
layout?: BlockLayout;
}

export interface EditorMessageRunEvalRequest extends EditorMessageRequest {
action: "runeval";
validatorPlan: pxt.blocks.ValidatorPlan;
Expand All @@ -305,6 +323,16 @@ declare namespace pxt.editor {
xml: Promise<any>;
}

export interface EditorMessageRenderXmlResponse {
svg: SVGSVGElement;
resultXml: Promise<any>;
}

export interface EditorMessageRenderByBlockIdResponse {
svg: SVGSVGElement;
resultXml: Promise<any>;
}

export interface EditorMessageRenderPythonRequest extends EditorMessageRequest {
action: "renderpython";
// typescript code to render
Expand Down Expand Up @@ -398,6 +426,15 @@ declare namespace pxt.editor {
restriction: pxt.editor.LanguageRestriction;
}

export interface EditorMessageGetToolboxCategoriesRequest extends EditorMessageRequest {
action: "gettoolboxcategories";
advanced?: boolean;
}

export interface EditorMessageGetToolboxCategoriesResponse {
categories: pxt.editor.ToolboxCategoryDefinition[];
}

export interface DataStreams<T> {
console?: T;
messages?: T;
Expand Down Expand Up @@ -927,10 +964,13 @@ declare namespace pxt.editor {
blocksScreenshotAsync(pixelDensity?: number, encodeBlocks?: boolean): Promise<string>;
renderBlocksAsync(req: pxt.editor.EditorMessageRenderBlocksRequest): Promise<pxt.editor.EditorMessageRenderBlocksResponse>;
renderPythonAsync(req: pxt.editor.EditorMessageRenderPythonRequest): Promise<pxt.editor.EditorMessageRenderPythonResponse>;
renderXml(req: pxt.editor.EditorMessageRenderXmlRequest): pxt.editor.EditorMessageRenderXmlResponse;
renderByBlockIdAsync(req: pxt.editor.EditorMessageRenderByBlockIdRequest): Promise<pxt.editor.EditorMessageRenderByBlockIdResponse>;

// FIXME (riknoll) need to figure out how to type this better
// getBlocks(): Blockly.Block[];
getBlocks(): any[];
getToolboxCategories(advanced?: boolean): pxt.editor.EditorMessageGetToolboxCategoriesResponse;

toggleHighContrast(): void;
setHighContrast(on: boolean): void;
Expand Down Expand Up @@ -1218,4 +1258,4 @@ declare namespace pxt.workspace {

fireEvent?: (ev: pxt.editor.EditorEvent) => void;
}
}
}
29 changes: 28 additions & 1 deletion pxteditor/editorcontroller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,26 @@ export function bindEditorMessages(getEditorAsync: () => Promise<IProjectView>)
})
});
}
case "renderxml": {
const rendermsg = data as pxt.editor.EditorMessageRenderXmlRequest;
return Promise.resolve()
.then(() => {
const r = projectView.renderXml(rendermsg);
return r.resultXml.then((svg: any) => {
resp = svg.xml;
})
});
}
case "renderbyblockid": {
const rendermsg = data as pxt.editor.EditorMessageRenderByBlockIdRequest;
return Promise.resolve()
.then(() => projectView.renderByBlockIdAsync(rendermsg))
.then(r => {
return r.resultXml.then((svg: any) => {
resp = svg.xml;
})
});
}
case "runeval": {
const evalmsg = data as pxt.editor.EditorMessageRunEvalRequest;
const plan = evalmsg.validatorPlan;
Expand All @@ -166,6 +186,13 @@ export function bindEditorMessages(getEditorAsync: () => Promise<IProjectView>)
resp = { result: results };
});
}
case "gettoolboxcategories": {
const msg = data as pxt.editor.EditorMessageGetToolboxCategoriesRequest;
return Promise.resolve()
.then(() => {
resp = projectView.getToolboxCategories(msg.advanced);
});
}
case "renderpython": {
const rendermsg = data as pxt.editor.EditorMessageRenderPythonRequest;
return Promise.resolve()
Expand Down Expand Up @@ -346,4 +373,4 @@ export function postHostMessageAsync(msg: pxt.editor.EditorMessageRequest): Prom
if (!msg.response)
resolve(undefined)
})
}
}
8 changes: 8 additions & 0 deletions pxtlib/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1426,6 +1426,14 @@ namespace ts.pxtc.Util {
return (n || "").split(/(?=[A-Z])/g).join(" ").toLowerCase();
}

export function camelCaseToLowercaseWithSpaces(n: string) {
return n.replace(/([A-Z])/gm, ' $1').toLocaleLowerCase().trim();
}

export function snakeCaseToLowercaseWithSpaces(n: string) {
return n.replace(/_/g, ' ').toLocaleLowerCase().trim();
}

export function range(len: number) {
let r: number[] = []
for (let i = 0; i < len; ++i) r.push(i)
Expand Down
38 changes: 37 additions & 1 deletion pxtservices/iframeDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,42 @@ export class IframeDriver {
return (resp.resp as pxt.editor.EditorMessageRenderPythonResponse).python;
}

async renderXml(xml: string) {
const resp = await this.sendRequest(
{
type: "pxteditor",
action: "renderxml",
xml
} as pxt.editor.EditorMessageRenderXmlRequest
) as pxt.editor.EditorMessageResponse;

return resp.resp;
}

async renderByBlockId(blockId: string) {
const resp = await this.sendRequest(
{
type: "pxteditor",
action: "renderbyblockid",
blockId: blockId
} as pxt.editor.EditorMessageRenderByBlockIdRequest
) as pxt.editor.EditorMessageResponse;

return resp.resp;
}

async getToolboxCategories(advanced?: boolean): Promise<pxt.editor.ToolboxCategoryDefinition[]> {
const resp = await this.sendRequest(
{
type: "pxteditor",
action: "gettoolboxcategories",
advanced
} as pxt.editor.EditorMessageGetToolboxCategoriesRequest
) as pxt.editor.EditorMessageResponse;

return (resp.resp as pxt.editor.EditorMessageGetToolboxCategoriesResponse).categories;
}

async runValidatorPlan(validatorPlan: pxt.blocks.ValidatorPlan, planLib: pxt.blocks.ValidatorPlan[]) {
const resp = await this.sendRequest(
{
Expand Down Expand Up @@ -550,4 +586,4 @@ export class IframeDriver {
}
}
}
}
}
8 changes: 4 additions & 4 deletions react-common/components/controls/LazyImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export interface LazyImageProps extends ControlProps {
src: string;
alt: string;
title?: string;
loadingElement?: JSX.Element;
}

let observer: IntersectionObserver;
Expand All @@ -20,6 +21,7 @@ export const LazyImage = (props: LazyImageProps) => {
ariaLabel,
ariaHidden,
ariaDescribedBy,
loadingElement,
} = props;

initObserver();
Expand All @@ -34,9 +36,8 @@ export const LazyImage = (props: LazyImageProps) => {
observer.observe(ref);
}



return <div className="common-lazy-image-wrapper">
<div className="loading-element">{loadingElement ? loadingElement : <div className="common-spinner" />}</div>
<img
id={id}
ref={handleImageRef}
Expand All @@ -49,7 +50,6 @@ export const LazyImage = (props: LazyImageProps) => {
aria-hidden={ariaHidden}
aria-describedby={ariaDescribedBy}
/>
<div className="common-spinner" />
<i className="fas fa-image" aria-hidden={true} />
</div>
}
Expand Down Expand Up @@ -85,4 +85,4 @@ function initObserver() {
})
}
observer = new IntersectionObserver(onIntersection, config);
}
}
10 changes: 6 additions & 4 deletions react-common/styles/controls/LazyImage.less
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
align-items: center;

.common-spinner {
position: absolute;
width: 60px;
height: 60px;
}

.loading-element {
position: absolute;
opacity: 1;
transition: opacity 0.3s ease;
}
Expand All @@ -28,7 +30,7 @@
}

.common-lazy-image-wrapper.loaded {
.common-spinner {
.loading-element {
opacity: 0;
}

Expand All @@ -42,7 +44,7 @@
}

.common-lazy-image-wrapper.error {
.common-spinner {
.loading-element {
opacity: 0;
}

Expand All @@ -53,4 +55,4 @@
img {
opacity: 0;
}
}
}
2 changes: 2 additions & 0 deletions teachertool/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { loadValidatorPlansAsync } from "./transforms/loadValidatorPlansAsync";
import { tryLoadLastActiveRubricAsync } from "./transforms/tryLoadLastActiveRubricAsync";
import { ImportRubricModal } from "./components/ImportRubricModal";
import { ConfirmationModal } from "./components/ConfirmationModal";
import { BlockPickerModal } from "./components/BlockPickerModal";

export const App = () => {
const { state, dispatch } = useContext(AppStateContext);
Expand Down Expand Up @@ -59,6 +60,7 @@ export const App = () => {
<CatalogModal />
<ImportRubricModal />
<ConfirmationModal />
<BlockPickerModal />
<Toasts />
</>
);
Expand Down
3 changes: 2 additions & 1 deletion teachertool/src/components/AddCriteriaButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { AppStateContext } from "../state/appStateContext";
import { useContext, useMemo } from "react";
import { classList } from "react-common/components/util";
import { Strings } from "../constants";
import { CatalogDisplayOptions } from "../types/modalOptions";

interface IProps {}

Expand All @@ -19,7 +20,7 @@ export const AddCriteriaButton: React.FC<IProps> = ({}) => {
<Button
className={classList("inline", "outline-button")}
label={Strings.AddCriteria}
onClick={() => showModal("catalog-display")}
onClick={() => showModal({ modal: "catalog-display" } as CatalogDisplayOptions)}
title={Strings.AddCriteria}
leftIcon="fas fa-plus-circle"
disabled={!hasAvailableCriteria}
Expand Down
Loading