问:
Angular D3 tree does not collapse back into its parent
We were able to use this example for Angular here(https://bl.ocks.org/d3noob/1a96af738c89b88723eb63456beb6510) and achieve the collapsible tree diagram. But it's not collapse back into its parent or our click action is not working properly.

Here is my code:
https://stackblitz.com/edit/angular-ivy-acd2yd?file=src/app/app.component.ts

答:
This answer is continues of the another answer. I improve the stackblitz to don't hardcode the "margins". I know I could edit the answer but there're a lot of changes. So first I want to explain a tree work.

When we write

```<code>this.treemap = d3.tree().size([100,100]);
</code>```

This calculate the positions of the nodes (x and y) in the way the "dots" are contains in a rectangle of 100x100px. So we can "scale" in the way

```<code>nodes.forEach((d: any) => {
  d.y = d.depth * step+innerMargin;
  d.x=this.height/2+(d.x-50)*this.height/100
});
</code>```

where "this.height" is the "height" of the svg and step is the disante between two nodes.

So, first defined several inputs that we need:
variables we need

```<code>  @Input() set treeData(value) {
    this._treeData = value;
    this.maxDepth = this.depthOfTree(this._treeData);
  }

  get treeData() {
    return this._treeData;
  }

  @Input() duration = 750;

  @Input('max-height') set __(value: number) {
    this.maxHeight = value;
  }
  @Input('aspect-ratio') set _(value: number | string) {
    const split = ('' + value).split(':');
    this.factor = +split[1] / +split[0];
  }
</code>```

See that we store in variables this.factor the "aspect-ratio" and we use a "getter" with threeData to get the "maxDepth"

I want to know the size of the text, so I want to create an array of strings with the text and draw with a style "visiblility:hidden". I want also get the first of the text and the larger text so we use

```<code>  labels: string[] = [];
  margin = { right: 100, left: 100 };
  firstLabel: any;
  lastLabel: any;
</code>```

I write a template like

```<code><span #label *ngFor="let label of labels" class='fade'>
   {{label}}
</span>
<div #wrapper id="tree" [attr.data-size]="size$|async" class="wrapper">
   <svg></svg>
</div>
</code>```

I want to change the font-size using media-queries, so I go to use ViewEncapsultion.None. This makes that the .css was to all the application, so, for avoid confict, we prexis all the .css with the selector of the component. futhermore. I choose use css variables. This allow we can change the colors of the nodes using this variables.

```<code>  d3noob-collapsible-tree .wrapper{
    position:relative;
    max-width:960px;
    margin-left:auto;
    margin-right:auto;
    text-align:center;
  }
  d3noob-collapsible-tree .fade{
    display:inline-block;
    border:1px solid black;
    position:absolute;
    visibility:hidden;
  }
  d3noob-collapsible-tree .node circle {
    stroke-width: var(--circle-stroke-width,1px);
    stroke: var(--circle-stroke,steelblue);;
  }
  d3noob-collapsible-tree .node.fill {
    fill: var(--circle-fill,lightsteelblue);;
  }

  d3noob-collapsible-tree .link {
    stroke:var(--stroke-link,#ccc);
    stroke-width: var(--stroke-width-link,1px);
  }
  d3noob-collapsible-tree .node text,d3noob-collapsible-tree .fade {
    font-family: sans-serif;
    font-size: .675em;
  }
  d3noob-collapsible-tree .node circle {
    fill: var(--circle-empty,white);
  }

  d3noob-collapsible-tree .link {
    fill: none;
  }

  @media (min-width: 400px) {
    d3noob-collapsible-tree .node text,d3noob-collapsible-tree .fade {
      font-size: .75em;
    }
  }
  @media (min-width: 600px) {
    d3noob-collapsible-tree .node text,d3noob-collapsible-tree .fade {
      font-size: .875em;
    }
  }
</code>```

We can in styles. css use some like

```<code>d3noob-collapsible-tree
{
  --stroke-link:#FFC0CB;
  --stroke-width-link:1px;
  --circle-empty:#FFC0CB;
  --circle-fill:#FF69B4;
  --circle-stroke:#C71585;
  --circle-stroke-width:0;
}
d3noob-collapsible-tree .node circle {
  filter: drop-shadow(1px 1px 2px rgba(0,0,0,.15));
}
</code>```

Well now, we are using ngAfterViewInit to create the tree and get the "firstLabel" (the #label of the "main node") and the "lastLabel" (the label with the larger width)

```<code>  @ViewChildren('label') labelsDiv: QueryList<ElementRef>;
  firstLabel: any;
  lastLabel: any;

  ngAfterViewInit(): void {
    this.firstLabel = this.labelsDiv.first.nativeElement;
    this.labelsDiv.forEach((x) => {
      this.lastLabel = !this.lastLabel
        ? x.nativeElement
        : this.lastLabel.getBoundingClientRect().width <
          x.nativeElement.getBoundingClientRect()
        ? x.nativeElement
        : this.lastLabel;
    });
    this.svg = d3.select('#tree').select('svg');
    this.svg.attr('preserveAspectRatio', 'xMidYMid meet').append('g');

    // declares a tree layout and assigns the size
    this.treemap = d3.tree().size([100, 100]);

    // Assigns parent, children, height, depth
    this.root = d3.hierarchy(this.treeData, (d: any) => {
      return d.children;
    });

    this.updateSize();
    setTimeout(() => {
      this.updateSize();
      this.root.children.forEach((d: any) => {
        this.collapse(d);
      });
      this.update(this.root);
    });
  }
</code>```

The updateSize change the size of the svg taking account of the "margin"

```<code>  updateSize() {
    this.margin.left = this.firstLabel.getBoundingClientRect().width + 25;
    this.margin.right = this.lastLabel.getBoundingClientRect().width + 50;
    this.width = this.wrapper.nativeElement.getBoundingClientRect().width;
    if (this.factor)
      this.height =
        this.width * this.factor < this.maxHeight
          ? this.width * this.factor
          : this.maxHeight;
    else this.height = this.maxHeight;

    this.svg
      .attr('preserveAspectRatio', 'xMidYMid meet')
      .attr('width', this.width + 'px')
      .attr('height', this.height + 'px')
      .attr(
        'viewBox',
        '-' + this.margin.left + ' 0 ' + this.width + ' ' + this.height
      );
  }
</code>```

See that we use the width and height to create the viewBox and the width and height and we use -magin.left in viewPost to "horizontal translate" the node-

The update is only the translate to typescript the functions in JS

```<code>  update(source: any) {
    // Assigns the x and y position for the nodes
    const treeData = this.treemap(this.root);

    // Compute the new tree layout.
    const nodes = treeData.descendants();
    const links = treeData.descendants().slice(1);

    let step =
      (this.width - this.margin.left - this.margin.right) / this.maxDepth;
    let innerMargin = 0;
    if (step > this.lastLabel.getBoundingClientRect().width + 100) {
      step = this.lastLabel.getBoundingClientRect().width + 100;
      innerMargin =
        (this.width -
          step * this.maxDepth -
          this.margin.left -
          this.margin.right -
          10) /
        2;
    }
    this.root.x0 = this.height / 2;
    this.root.y0 = 0;
    // Normalize for fixed-depth.
    nodes.forEach((d: any) => {
      d.y = d.depth * step + innerMargin;
      d.x = this.height / 2 + ((d.x - 50) * this.height) / 100;
    });
    // ****************** Nodes section ***************************

    // Update the nodes...
    const node = this.svg.selectAll('g.node').data(nodes, (d: any) => {
      return d.id || (d.id = ++this.i);
    });

    // Enter any new modes at the parent's previous position.
    const nodeEnter = node
      .enter()
      .append('g')
      .attr('class', 'node')
      .attr('transform', (d: any) => {
        return 'translate(' + source.y0 + ',' + source.x0 + ')';
      })
      .on('click', (_, d) => this.click(d));

    // Add Circle for the nodes
    nodeEnter
      .append('circle')
      .attr('class', (d: any) => (d._children ? 'node fill' : 'node'))
      .attr('r', 1e-6);
    // Add labels for the nodes
    nodeEnter
      .append('text')
      .attr('text-rendering', 'optimizeLegibility')
      .attr('dy', '.35em')

      .attr('cursor', (d) => (d.children || d._children ? 'pointer' : 'auto'))
      .attr('x', (d) => {
        return d.children || d._children ? -13 : 13;
      })
      .attr('text-anchor', (d: any) => {
        return d.children || d._children ? 'end' : 'start';
      })
      .text((d) => {
        return d.data.name;
      });
    // UPDATE
    const nodeUpdate = nodeEnter.merge(node);

    // Transition to the proper position for the node
    nodeUpdate
      .transition()
      .duration(this.duration)
      .attr('transform', (d: any) => {
        return 'translate(' + d.y + ',' + d.x + ')';
      });

    // Update the node attributes and style
    nodeUpdate
      .select('circle.node')
      .attr('r', 10)
      .attr('class', (d: any) => (d._children ? 'node fill' : 'node'))
      .attr('cursor', (d) => (d.children || d._children ? 'pointer' : 'auto'));

    // Remove any exiting nodes
    const nodeExit = node
      .exit()
      .transition()
      .duration(this.duration)
      .attr('transform', (d: any) => {
        return 'translate(' + source.y + ',' + source.x + ')';
      })
      .remove();

    // On exit reduce the node circles size to 0
    nodeExit.select('circle').attr('r', 1e-6);

    // On exit reduce the opacity of text labels
    nodeExit.select('text').style('fill-opacity', 1e-6);

    // ****************** links section ***************************

    // Update the links...
    const link = this.svg.selectAll('path.link').data(links, (d: any) => {
      return d.id;
    });

    // Enter any new links at the parent's previous position.
    const linkEnter = link
      .enter()
      .insert('path', 'g')
      .attr('class', 'link')
      .attr('d', (d: any) => {
        const o = { x: source.x0, y: source.y0 };
        return this.diagonal(o, o);
      });

    // UPDATE
    const linkUpdate = linkEnter.merge(link);

    // Transition back to the parent element position
    linkUpdate
      .transition()
      .duration(this.duration)
      .attr('d', (d: any) => {
        return this.diagonal(d, d.parent);
      });

    // Remove any exiting links
    const linkExit = link
      .exit()
      .transition()
      .duration(this.duration)
      .attr('d', (d: any) => {
        const o = { x: source.x, y: source.y };
        return this.diagonal(o, o);
      })
      .remove();

    // Store the old positions for transition.
    nodes.forEach((d: any) => {
      d.x0 = d.x;
      d.y0 = d.y;
    });
  }
</code>```

Thanks you for reading, the final stackblitz

Body:
This answer is continues of the another answer. I improve the stackblitz to don't hardcode the "margins". I know I could edit the answer but there're a lot of changes. So first I want to explain a tree work.

When we write

this.treemap = d3.tree().size([100,100]);

This calculate the positions of the nodes (x and y) in the way the "dots" are contains in a rectangle of 100x100px. So we can "scale" in the way

nodes.forEach((d: any) => {
  d.y = d.depth * step+innerMargin;
  d.x=this.height/2+(d.x-50)*this.height/100
});

where "this.height" is the "height" of the svg and step is the disante between two nodes.

So, first defined several inputs that we need:
variables we need

  @Input() set treeData(value) {
    this._treeData = value;
    this.maxDepth = this.depthOfTree(this._treeData);
  }

  get treeData() {
    return this._treeData;
  }

  @Input() duration = 750;

  @Input('max-height') set __(value: number) {
    this.maxHeight = value;
  }
  @Input('aspect-ratio') set _(value: number | string) {
    const split = ('' + value).split(':');
    this.factor = +split[1] / +split[0];
  }

See that we store in variables this.factor the "aspect-ratio" and we use a "getter" with threeData to get the "maxDepth"

I want to know the size of the text, so I want to create an array of strings with the text and draw with a style "visiblility:hidden". I want also get the first of the text and the larger text so we use

  labels: string[] = [];
  margin = { right: 100, left: 100 };
  firstLabel: any;
  lastLabel: any;

I write a template like

<span #label *ngFor="let label of labels" class='fade'>
   {{label}}
</span>
<div #wrapper id="tree" [attr.data-size]="size$|async" class="wrapper">
   <svg></svg>
</div>

I want to change the font-size using media-queries, so I go to use ViewEncapsultion.None. This makes that the .css was to all the application, so, for avoid confict, we prexis all the .css with the selector of the component. futhermore. I choose use css variables. This allow we can change the colors of the nodes using this variables.

  d3noob-collapsible-tree .wrapper{
    position:relative;
    max-width:960px;
    margin-left:auto;
    margin-right:auto;
    text-align:center;
  }
  d3noob-collapsible-tree .fade{
    display:inline-block;
    border:1px solid black;
    position:absolute;
    visibility:hidden;
  }
  d3noob-collapsible-tree .node circle {
    stroke-width: var(--circle-stroke-width,1px);
    stroke: var(--circle-stroke,steelblue);;
  }
  d3noob-collapsible-tree .node.fill {
    fill: var(--circle-fill,lightsteelblue);;
  }

  d3noob-collapsible-tree .link {
    stroke:var(--stroke-link,#ccc);
    stroke-width: var(--stroke-width-link,1px);
  }
  d3noob-collapsible-tree .node text,d3noob-collapsible-tree .fade {
    font-family: sans-serif;
    font-size: .675em;
  }
  d3noob-collapsible-tree .node circle {
    fill: var(--circle-empty,white);
  }

  d3noob-collapsible-tree .link {
    fill: none;
  }

  @media (min-width: 400px) {
    d3noob-collapsible-tree .node text,d3noob-collapsible-tree .fade {
      font-size: .75em;
    }
  }
  @media (min-width: 600px) {
    d3noob-collapsible-tree .node text,d3noob-collapsible-tree .fade {
      font-size: .875em;
    }
  }

We can in styles. css use some like

d3noob-collapsible-tree
{
  --stroke-link:#FFC0CB;
  --stroke-width-link:1px;
  --circle-empty:#FFC0CB;
  --circle-fill:#FF69B4;
  --circle-stroke:#C71585;
  --circle-stroke-width:0;
}
d3noob-collapsible-tree .node circle {
  filter: drop-shadow(1px 1px 2px rgba(0,0,0,.15));
}

Well now, we are using ngAfterViewInit to create the tree and get the "firstLabel" (the #label of the "main node") and the "lastLabel" (the label with the larger width)

  @ViewChildren('label') labelsDiv: QueryList<ElementRef>;
  firstLabel: any;
  lastLabel: any;

  ngAfterViewInit(): void {
    this.firstLabel = this.labelsDiv.first.nativeElement;
    this.labelsDiv.forEach((x) => {
      this.lastLabel = !this.lastLabel
        ? x.nativeElement
        : this.lastLabel.getBoundingClientRect().width <
          x.nativeElement.getBoundingClientRect()
        ? x.nativeElement
        : this.lastLabel;
    });
    this.svg = d3.select('#tree').select('svg');
    this.svg.attr('preserveAspectRatio', 'xMidYMid meet').append('g');

    // declares a tree layout and assigns the size
    this.treemap = d3.tree().size([100, 100]);

    // Assigns parent, children, height, depth
    this.root = d3.hierarchy(this.treeData, (d: any) => {
      return d.children;
    });

    this.updateSize();
    setTimeout(() => {
      this.updateSize();
      this.root.children.forEach((d: any) => {
        this.collapse(d);
      });
      this.update(this.root);
    });
  }

The updateSize change the size of the svg taking account of the "margin"

  updateSize() {
    this.margin.left = this.firstLabel.getBoundingClientRect().width + 25;
    this.margin.right = this.lastLabel.getBoundingClientRect().width + 50;
    this.width = this.wrapper.nativeElement.getBoundingClientRect().width;
    if (this.factor)
      this.height =
        this.width * this.factor < this.maxHeight
          ? this.width * this.factor
          : this.maxHeight;
    else this.height = this.maxHeight;

    this.svg
      .attr('preserveAspectRatio', 'xMidYMid meet')
      .attr('width', this.width + 'px')
      .attr('height', this.height + 'px')
      .attr(
        'viewBox',
        '-' + this.margin.left + ' 0 ' + this.width + ' ' + this.height
      );
  }

See that we use the width and height to create the viewBox and the width and height and we use -magin.left in viewPost to "horizontal translate" the node-

The update is only the translate to typescript the functions in JS

  update(source: any) {
    // Assigns the x and y position for the nodes
    const treeData = this.treemap(this.root);

    // Compute the new tree layout.
    const nodes = treeData.descendants();
    const links = treeData.descendants().slice(1);

    let step =
      (this.width - this.margin.left - this.margin.right) / this.maxDepth;
    let innerMargin = 0;
    if (step > this.lastLabel.getBoundingClientRect().width + 100) {
      step = this.lastLabel.getBoundingClientRect().width + 100;
      innerMargin =
        (this.width -
          step * this.maxDepth -
          this.margin.left -
          this.margin.right -
          10) /
        2;
    }
    this.root.x0 = this.height / 2;
    this.root.y0 = 0;
    // Normalize for fixed-depth.
    nodes.forEach((d: any) => {
      d.y = d.depth * step + innerMargin;
      d.x = this.height / 2 + ((d.x - 50) * this.height) / 100;
    });
    // ****************** Nodes section ***************************

    // Update the nodes...
    const node = this.svg.selectAll('g.node').data(nodes, (d: any) => {
      return d.id || (d.id = ++this.i);
    });

    // Enter any new modes at the parent's previous position.
    const nodeEnter = node
      .enter()
      .append('g')
      .attr('class', 'node')
      .attr('transform', (d: any) => {
        return 'translate(' + source.y0 + ',' + source.x0 + ')';
      })
      .on('click', (_, d) => this.click(d));

    // Add Circle for the nodes
    nodeEnter
      .append('circle')
      .attr('class', (d: any) => (d._children ? 'node fill' : 'node'))
      .attr('r', 1e-6);
    // Add labels for the nodes
    nodeEnter
      .append('text')
      .attr('text-rendering', 'optimizeLegibility')
      .attr('dy', '.35em')

      .attr('cursor', (d) => (d.children || d._children ? 'pointer' : 'auto'))
      .attr('x', (d) => {
        return d.children || d._children ? -13 : 13;
      })
      .attr('text-anchor', (d: any) => {
        return d.children || d._children ? 'end' : 'start';
      })
      .text((d) => {
        return d.data.name;
      });
    // UPDATE
    const nodeUpdate = nodeEnter.merge(node);

    // Transition to the proper position for the node
    nodeUpdate
      .transition()
      .duration(this.duration)
      .attr('transform', (d: any) => {
        return 'translate(' + d.y + ',' + d.x + ')';
      });

    // Update the node attributes and style
    nodeUpdate
      .select('circle.node')
      .attr('r', 10)
      .attr('class', (d: any) => (d._children ? 'node fill' : 'node'))
      .attr('cursor', (d) => (d.children || d._children ? 'pointer' : 'auto'));

    // Remove any exiting nodes
    const nodeExit = node
      .exit()
      .transition()
      .duration(this.duration)
      .attr('transform', (d: any) => {
        return 'translate(' + source.y + ',' + source.x + ')';
      })
      .remove();

    // On exit reduce the node circles size to 0
    nodeExit.select('circle').attr('r', 1e-6);

    // On exit reduce the opacity of text labels
    nodeExit.select('text').style('fill-opacity', 1e-6);

    // ****************** links section ***************************

    // Update the links...
    const link = this.svg.selectAll('path.link').data(links, (d: any) => {
      return d.id;
    });

    // Enter any new links at the parent's previous position.
    const linkEnter = link
      .enter()
      .insert('path', 'g')
      .attr('class', 'link')
      .attr('d', (d: any) => {
        const o = { x: source.x0, y: source.y0 };
        return this.diagonal(o, o);
      });

    // UPDATE
    const linkUpdate = linkEnter.merge(link);

    // Transition back to the parent element position
    linkUpdate
      .transition()
      .duration(this.duration)
      .attr('d', (d: any) => {
        return this.diagonal(d, d.parent);
      });

    // Remove any exiting links
    const linkExit = link
      .exit()
      .transition()
      .duration(this.duration)
      .attr('d', (d: any) => {
        const o = { x: source.x, y: source.y };
        return this.diagonal(o, o);
      })
      .remove();

    // Store the old positions for transition.
    nodes.forEach((d: any) => {
      d.x0 = d.x;
      d.y0 = d.y;
    });
  }

Thanks you for reading, the final stackblitz


来源: stackexchange

问:
Bitbucket pipelines - Run or skip step based on build output
We have a monorepo that contains about 5 projects. All these projects are build based on the git change history, so if project A is not changed, it is not build. This is al managed by Nx monorepo.

We are using Bitbucket Pipelines to build and deploy our projects. We want to split every deploy into it's own step so that we have more control over each project's deployment.

In order to achieve this we need to change our build step so that it only executes if the dist folder contains the portal it is ment to deploy. I've read about the condition configuration, but i cannot find anything about checking build artifacts in a condition instead of the git commit that triggerd the change. So is there a way to skip (or directly pass) a step if the portal is not in the build artifact?

Build step

```<code>- step: &build
    name: Build
    caches:
      - node
    script:
      - git fetch origin master:refs/remotes/master
      - npm run build
    artifacts:
      - dist/**
</code>```

Example Dist artifact

```<code>.
├── dist/
│   ├── login-portal
│   ├── Portal-Y
</code>```

Our deploy step

```<code>- step: &deployLoginPortal
    image: amazon/aws-cli:2.4.17
    deployment: test
    trigger: manual
    script:
      - aws s3 sync $LOGIN_OUTPUT_PATH s3://$LOGIN_S3_BUCKET/ --acl public-read # Sync the portal

# $LOGIN_OUTPUT_PATH = 'dist/login-portal'
</code>```

Example condition (does not work)

```<code>condition:
  changesets:
    includePaths:
      - $LOGIN_OUTPUT_PATH/** # only run if dist contains changes in $LOGIN_BUILD_PATH
</code>```

Am I missing something or is there an other way of only executing the step if the build artifact (dist/) contains the portal the step is ment to deploy?

答:
You can manually check the presence of an artifact before doing aws s3 sync and gracefully exit the step if condition is not satisfied:

script:
  - [ ! -d "$LOGIN_OUTPUT_PATH" ] && echo "Directory $LOGIN_OUTPUT_PATH is not present; gracefully exiting" && exit 0
  - aws s3 sync $LOGIN_OUTPUT_PATH s3://$LOGIN_S3_BUCKET/ --acl public-read
```

Be advised that your step will still technically be triggered, so its startup time (usually about 40 seconds) will be affecting your quotas.

ContentLicense: CC BY-SA 4.0

Body:
We have a monorepo that contains about 5 projects. All these projects are build based on the git change history, so if project A is not changed, it is not build. This is al managed by Nx monorepo.

We are using Bitbucket Pipelines to build and deploy our projects. We want to split every deploy into it's own step so that we have more control over each project's deployment.

In order to achieve this we need to change our build step so that it only executes if the dist folder contains the portal it is ment to deploy. I've read about the condition configuration, but i cannot find anything about checking build artifacts in a condition instead of the git commit that triggerd the change. So is there a way to skip (or directly pass) a step if the portal is not in the build artifact?

Build step

- step: &build
    name: Build
    caches:
      - node
    script:
      - git fetch origin master:refs/remotes/master
      - npm run build
    artifacts:
      - dist/**

Example Dist artifact

.
├── dist/
│   ├── login-portal
│   ├── Portal-Y

Our deploy step

- step: &deployLoginPortal
    image: amazon/aws-cli:2.4.17
    deployment: test
    trigger: manual
    script:
      - aws s3 sync $LOGIN_OUTPUT_PATH s3://$LOGIN_S3_BUCKET/ --acl public-read # Sync the portal

# $LOGIN_OUTPUT_PATH = 'dist/login-portal'

Example condition (does not work)

condition:
  changesets:
    includePaths:
      - $LOGIN_OUTPUT_PATH/** # only run if dist contains changes in $LOGIN_BUILD_PATH

Am I missing something or is there an other way of only executing the step if the build artifact (dist/) contains the portal the step is ment to deploy?

Body:
You can manually check the presence of an artifact before doing aws s3 sync and gracefully exit the step if condition is not satisfied:

script:
  - [ ! -d "$LOGIN_OUTPUT_PATH" ] && echo "Directory $LOGIN_OUTPUT_PATH is not present; gracefully exiting" && exit 0
  - aws s3 sync $LOGIN_OUTPUT_PATH s3://$LOGIN_S3_BUCKET/ --acl public-read

Be advised that your step will still technically be triggered, so its startup time (usually about 40 seconds) will be affecting your quotas.


问:
Bigquery nested table resulting out different results for similar queries
I have Bigquery table with Record type 'trigger_prop' column and here are two ways using which I am querying but it is resulting out different output:

First Query:

```<code>SELECT b.* FROM dataset.table a, unnest(trigger_prop) as b
where b.number=425600;
</code>```

Second Query:

```<code>SELECT a.trigger_prop FROM dataset.table a, unnest(trigger_prop) as b
where b.number=425600;
</code>```

'Query1 is resulting out 1 record', while 'query2 is resulting out 2 records' from table which are actual records. These both queries are doing same thing but resulting out different output. First query is returning less record while second query is returning actual records. Can someone please help me in understanding the difference in both queries?

答:
They are not doing the same thing, the difference is the SELECT a.trigger_prop vs SELECT b.* which are different tables.

The first query selects the unnested translation of trigger_propfrom table b which "unfolds" the array and keeps the single array item with number=425600.

The second query selects the raw trigger_prop field from the source table and returns a single row, but this row has multiple array items in it so it looks like multiple rows because of the array in trigger_prop.

To demonstrate I ran the following query, note the LIMIT 1 clause:

```<code>WITH
  TABLE AS (
  SELECT
    ARRAY<STRUCT<number INTEGER,
    name STRING>>[(1,
      "me"),
    (2,
      "you")] AS trigger_prop)
SELECT
  a.trigger_prop
FROM
  TABLE AS a,
  UNNEST(trigger_prop) AS b
WHERE
  b.number=1
LIMIT 1
</code>```

This gives the following result, note how it's a single row which looks like multiple rows.

Body:
I have Bigquery table with Record type 'trigger_prop' column and here are two ways using which I am querying but it is resulting out different output:

First Query:

SELECT b.* FROM dataset.table a, unnest(trigger_prop) as b
where b.number=425600;

Second Query:

SELECT a.trigger_prop FROM dataset.table a, unnest(trigger_prop) as b
where b.number=425600;

'Query1 is resulting out 1 record', while 'query2 is resulting out 2 records' from table which are actual records. These both queries are doing same thing but resulting out different output. First query is returning less record while second query is returning actual records. Can someone please help me in understanding the difference in both queries?

Body:
They are not doing the same thing, the difference is the SELECT a.trigger_prop vs SELECT b.* which are different tables.

The first query selects the unnested translation of trigger_propfrom table b which "unfolds" the array and keeps the single array item with number=425600.

The second query selects the raw trigger_prop field from the source table and returns a single row, but this row has multiple array items in it so it looks like multiple rows because of the array in trigger_prop.

To demonstrate I ran the following query, note the LIMIT 1 clause:

WITH
  TABLE AS (
  SELECT
    ARRAY<STRUCT<number INTEGER,
    name STRING>>[(1,
      "me"),
    (2,
      "you")] AS trigger_prop)
SELECT
  a.trigger_prop
FROM
  TABLE AS a,
  UNNEST(trigger_prop) AS b
WHERE
  b.number=1
LIMIT 1

This gives the following result, note how it's a single row which looks like multiple rows.


问:
How to update an array field on mongodb by pushing it if the element is not present and if it is present update it?
I am working on a IT ticketing system where every time a new comment or a note has been added to a ticket a notification needs to be send to the user who is following the ticket. Below code only inserts new ticket in list of tickets followed by the user if it is not already present, however if it is present it ignores it. What I need to do is if the ticket that has just been updated is already present, change clicked field to false. In my application's frontend, when user clicks the notification icon it will change clicked to TRUE but when a new comment is added clicked needs to be changed to FALSE so that the user gets notification that comment has been added to the same ticket. How do I go about achieving it?</p>
```<code>const ReqNotificationSchema = new Schema({
  user: { type: Schema.Types.ObjectId, ref: "User" },
  notifications: [
    {
      request: { type: Schema.Types.ObjectId, ref: "Request" },
      clicked: { type: Boolean, default: false },
    },
  ],
});

if(updated){

await ReqNotificationModel.findOneAndUpdate(
          {
            user: follower.user,
            "notifications.request": { $ne: updated._id },
          },
          {
            $push: { notifications: { request: updated._id, clicked: false } },
          },
          { new: true }
        );
}
</code>```

答:
I wasn't able to do it in one step , so I tried in a 2 step approach.</p>
```<code>const notification = await ReqNotificationModel.findOne({
          user: follower.user,
        });
        let index = notification.notifications
          .map((obj) => obj.request.toString())
          .indexOf(updated._id.toString());

        notification.notifications[index].clicked = false;

        await notification.save();
 });
</code>```

Body:
I am working on a IT ticketing system where every time a new comment or a note has been added to a ticket a notification needs to be send to the user who is following the ticket. Below code only inserts new ticket in list of tickets followed by the user if it is not already present, however if it is present it ignores it. What I need to do is if the ticket that has just been updated is already present, change clicked field to false. In my application's frontend, when user clicks the notification icon it will change clicked to TRUE but when a new comment is added clicked needs to be changed to FALSE so that the user gets notification that comment has been added to the same ticket. How do I go about achieving it?

const ReqNotificationSchema = new Schema({
  user: { type: Schema.Types.ObjectId, ref: "User" },
  notifications: [
    {
      request: { type: Schema.Types.ObjectId, ref: "Request" },
      clicked: { type: Boolean, default: false },
    },
  ],
});

if(updated){

await ReqNotificationModel.findOneAndUpdate(
          {
            user: follower.user,
            "notifications.request": { $ne: updated._id },
          },
          {
            $push: { notifications: { request: updated._id, clicked: false } },
          },
          { new: true }
        );
}

Body:
I wasn't able to do it in one step , so I tried in a 2 step approach.

const notification = await ReqNotificationModel.findOne({
          user: follower.user,
        });
        let index = notification.notifications
          .map((obj) => obj.request.toString())
          .indexOf(updated._id.toString());

        notification.notifications[index].clicked = false;

        await notification.save();
 });


问:
Remove leading zeros from string timestamp
Lua supports limited Expressions and Patterns

The time stamp is variable in the format DD:HH:MM:SS,FF (Days:Hours:Minutes:Seconds,Miliseconds)

The objective is to trim/truncate the timestamp by removing any leading zeros to represent as follow:

Example timestamps includes:

timestamp = 00:00:00:00,00 => 0

timestamp = 00:01:00:00,00 => 1:00:00,00

timestamp = 00:00:01:00,00 => 1:00,00

timestamp = 00:00:00:01,00 => 1,00

timestamp = 99:23:59:59,99 => 99:23:59:59,99

I am looking for a simple solution such as using gsub, TA

答:
Why not use string.match? The below code is based on the assumption that the input will be a valid timestamp. It handles all five cases correctly, but I'm not sure whether trimming something like 00:00:00:00,42 to 42 - which this does - is desired.

local function trim_timestamp(timestamp)
    return timestamp:match"^[0:,]*(.+)$"
end
```
<p>Otherwise, move the comma and the first digit of the seconds to the captured part:</p>
<pre class="lang-lua prettyprint-override"><code>local function trim_timestamp(timestamp)
    return timestamp:match"^[0:]*(%d,.+)$"
end
</code>```

Note that this will then turn the first example into 0,00; you'd have to explicitly handle the case of all zeroes:

local function trim_timestamp(timestamp)
    local trimmed = timestamp:match"^[0:]*(%d,.+)$"
    if trimmed == "0,00" then return "0" end -- shorten all zeroes
    return trimmed
end
```

Body:
Why not use string.match? The below code is based on the assumption that the input will be a valid timestamp. It handles all five cases correctly, but I'm not sure whether trimming something like 00:00:00:00,42 to 42 - which this does - is desired.

local function trim_timestamp(timestamp)
    return timestamp:match"^[0:,]*(.+)$"
end

Otherwise, move the comma and the first digit of the seconds to the captured part:

local function trim_timestamp(timestamp)
    return timestamp:match"^[0:]*(%d,.+)$"
end

Note that this will then turn the first example into 0,00; you'd have to explicitly handle the case of all zeroes:

local function trim_timestamp(timestamp)
    local trimmed = timestamp:match"^[0:]*(%d,.+)$"
    if trimmed == "0,00" then return "0" end -- shorten all zeroes
    return trimmed
end


问:
For loop inside for loop for generating strings
I have the following code generating an image url based on an array of objects and their properties:

```<code>for (let s = 0; s < amount; s++) {
   console.log(projects[s].imagelocation + projects[s].images[0]);
}
</code>```

As an example this gives me the following output:

```<code>img/EnergyGoStix-assets/GoStix1.jpg
img/Premier-assets/PremierStudios1.jpg
img/Quickstix-assets/QuickStix1.jpg
img/MotherMonster-assets/MotherMonster1.jpg
img/Stepping-assets/SteppingBooklet1.jpg
</code>```

However, the images property is actually an array. This array contains multiple image sources such as GoStix1.jpg, GoStix2.jpg, etc. This number of image sources varies between the projects.

How do I create a loop within a loop that would incorporate images.length where it will first go through each project and generate all image sources, prior to moving onto the next one?

P.S - Sorry for the terrible post title, had no idea what to call this. If anyone can come up with a better one to help be more precise, please let me know so I can update it.

答:
How about this?

```<code>for (let s = 0; s < amount; s++) {
for (let y in  projects[s].images){
   console.log(projects[s].imagelocation + projects[s].images[y]);
}
}

</code>```

If you want to display images array only in one console, use:

```<code>for (let s = 0; s < amount; s++) {
   console.log(projects[s].imagelocation + [...projects[s].images]);
}
</code>```

Body:
I have the following code generating an image url based on an array of objects and their properties:

for (let s = 0; s < amount; s++) {
   console.log(projects[s].imagelocation + projects[s].images[0]);
}

As an example this gives me the following output:

img/EnergyGoStix-assets/GoStix1.jpg
img/Premier-assets/PremierStudios1.jpg
img/Quickstix-assets/QuickStix1.jpg
img/MotherMonster-assets/MotherMonster1.jpg
img/Stepping-assets/SteppingBooklet1.jpg

However, the images property is actually an array. This array contains multiple image sources such as GoStix1.jpg, GoStix2.jpg, etc. This number of image sources varies between the projects.

How do I create a loop within a loop that would incorporate images.length where it will first go through each project and generate all image sources, prior to moving onto the next one?

P.S - Sorry for the terrible post title, had no idea what to call this. If anyone can come up with a better one to help be more precise, please let me know so I can update it.

Body:
How about this?

for (let s = 0; s < amount; s++) {
for (let y in  projects[s].images){
   console.log(projects[s].imagelocation + projects[s].images[y]);
}
}

If you want to display images array only in one console, use:

for (let s = 0; s < amount; s++) {
   console.log(projects[s].imagelocation + [...projects[s].images]);
}


问:
Open MySQL from the terminal
I have installed MySQL on my macbook and would like to access MySQL through the terminal by simply typing mysql. How do I do this?</p>

答:
```<code>echo 'export PATH=/usr/local/mysql/bin:$PATH' >> ~/.bash_profile

. ~/.bash_profile

mysql -u root -p
</code>```

ContentLicense: CC BY-SA 3.0

Title: Open MySQL from the terminal


问:
Sending transaction to Smart Contract (myContract.methods.myMethod.send() ) returns error: Unknown Account on mobile Wallets
The Dapp sends Bep20 token from a remote wallet(My wallet) to users after they perform a certain activity such as accepting BNB to be sent to ICO, it works well on a desktop in which metamask is installed. The code that executes this is:

    var amountTosend = amount;
     var privateKey = 'PRIVATE_KEY';

    var accountFrom = web3provider.eth.accounts.privateKeyToAccount(privateKey).address;
     var contractCall = contractInstance.methods.transfer(addressTo, "0x"+amountTosend.toString(16));
     var icoAccount = web3provider.eth.accounts.privateKeyToAccount(privateKey);
         web3provider.eth.accounts.wallet.add(icoAccount);
contractCall.send({ from: accountFrom, gas: 2000000 }).then(function(hashdata) {
                             console.log(hashdata);

                            var rawTransaction = {

                                     "from": accountFrom,
                                     "nonce": nonce,
                                     "gasPrice": 20000000000,

                                     "gas": gas,
                                     "to": SmartContractAddress,

                                     "value": "0x" + amountTosend.toString(16),

                                     "data": hashdata.events.Transfer.raw.data,

                                     "chainId": chainid
                                 };

                                 var privKey = new ethereumjs.Buffer.Buffer(privateKey, 'hex');

                                 let tx = new ethereumjs.Tx(rawTransaction);
                                 tx.sign(privKey)
                                 let serializedTx = tx.serialize();

                                 console.log('serializedTx:', serializedTx);

                                 web3provider.eth.sendSignedTransaction('0x' + serializedTx.toString('hex'), function(err, receipt) {
                                     if (!err) {
                                         console.log('success token sent to user: ' + receipt);
                                         alert('You have received your Tokens in your Wallet');
                                     } else {
                                         console.log('error: ' + err);
                                         alert("An error Occured: " + err);
                                     }
                                 });

})

```
<p>On mobile wallets such as trust and metamask mobile connected with web3modal using wallet connect as provider, I successfully interacted with the wallet, prompt user to send BNB but</p>
```contractCall.send({ from: accountFrom, gas: 2000000 })
```
<p>which is used to change the state of the smart contract to send user Bep20 token fails with Unknown account error after adding remote wallet to local using:</p>
```web3provider.eth.accounts.wallet.add(icoAccount);
```
<p><strong>Note:</strong> If I try skipping</p>
```contractCall.send({ from: accountFrom, gas: 2000000 })
```
<p>and use contractCall.encodeABI() for data parameter, it works fine but no token is actually sent to the user and I guess is because the smart contact state needs to be changed/altered with</p>
```myContract.methods.myMethod([param1[, param2[, ...]]]).send
```

Please I need any useful help/tip to make this work on mobile wallet, I have been on this bug for a few days now, thanks

答:
I finally fixed this error, and I will like to answer comprehensively for future visitors. The short answer will come first to implement the solution, and the long comprehensive answer afterward to help you understand better and learn the technicalities of fixing the bug

Note:  I am using walletconnect and web3modal under the hood for my DAPP on Mobile browser and Metamask for Desktop and I'm using vanilla javascript for web3 implemenation

Short Answer:
I had to set givenProvider to the currentProvider which was initialized on web3 instance and that was my RPC URL provider, for me my RPC URL provider is: https://getblock.io/ which was passed in walletconnect/web3modal provider options paramater

I'm connecting to BSC so my RPC URL is: https://bsc.getblock.io/mainnet/?api_key=API_KEY

You may use other RPC URL providers of your choice

So the givenProvider is set like this:

```<code>web3.givenProvider = web3.currentProvider;
web3.eth.givenProvider = web3.currentProvider;
web3.eth.accounts.givenProvider = web3.currentProvider;

</code>```

read walletconnect docs on setting provider(s) here: https://docs.walletconnect.com/quick-start/dapps/web3-provider

Setting the web3.givenProvider to web3.currentProvider fixed the issue as web3.givenProvider was null

Long Answer:

You need to understand what is currentProvider and givenProvider are, as the bug resolves around the web3 provider.
In my understanding as of writting this answer givenProvider is the provider injected in an Ethereum enabled browser while currentProvider is the  provider that you passed in on the initialization of web3.

The error is: Unknown account

This problem doesn't appear on a desktop browser where metamask is installed because injects the givenProvider, except of course is a remote account that doesn't exist on the provider node

You have to add the account to the provider node using:

```<code>  var account=  web3provider.eth.accounts.privateKeyToAccount(PRIVATE_KEY);
var addAccount = web3provider.eth.accounts.wallet.add(account);

</code>```

This solves the error on desktop browser without having to configure or set up much and that is because masks makes your browser Ethereum enabled and injects givenProvider

But for mobile browsers, you will face this issue because mobile browsers aren't Ethereum enabled environment. You will have to set givenProvider to a valid provider after initializing web3 through walletconenct.

Note: givenProvider talks to the blockchain through the web and it is null on mobile browsers. Console.log(web3) will show you the values of web3 instance

Putting all together your code should look like this:

```<code>
import WalletConnectProvider from "@walletconnect/web3-provider";
import Web3 from "web3";

//  Create WalletConnect Provider
const provider = new WalletConnectProvider({
  rpc: {
    1: "https://mainnet.mycustomnode.com",
    3: "https://ropsten.mycustomnode.com",
    100: "https://dai.poa.network",
    // ...
  },
});

await provider.enable();

//  Create Web3 instance
const web3 = new Web3(provider);

//FIX STARTS HERE

//set givenProvider to currentProvider
 web3.givenProvider = web3.currentProvider;
 web3.eth.givenProvider = web3.currentProvider;
 web3.eth.accounts.givenProvider = web3.currentProvider;

//add wallet to provider node
var account= web3.eth.accounts.privateKeyToAccount(PRIVATE_KEY);
var addAccount = web3.eth.accounts.wallet.add(account);
var accountFrom = account.address;

var gas = contractCall.estimateGas({ from: accountFrom });
 gas.then(function(gasTouse) {
contractCall.send({
from: accountFrom, gas: gasTouse }).then(function(hashdata){
   console.log(hashdata);

});
});
</code>```

Note: Be sure you estimate gas and include it, as without it you may encounter some gas-related errors.

Happy coding :)

Body:
The Dapp sends Bep20 token from a remote wallet(My wallet) to users after they perform a certain activity such as accepting BNB to be sent to ICO, it works well on a desktop in which metamask is installed. The code that executes this is:

    var amountTosend = amount;
     var privateKey = 'PRIVATE_KEY';

    var accountFrom = web3provider.eth.accounts.privateKeyToAccount(privateKey).address;
     var contractCall = contractInstance.methods.transfer(addressTo, "0x"+amountTosend.toString(16));
     var icoAccount = web3provider.eth.accounts.privateKeyToAccount(privateKey);
         web3provider.eth.accounts.wallet.add(icoAccount);
contractCall.send({ from: accountFrom, gas: 2000000 }).then(function(hashdata) {
                             console.log(hashdata);

                            var rawTransaction = {

                                     "from": accountFrom,
                                     "nonce": nonce,
                                     "gasPrice": 20000000000,

                                     "gas": gas,
                                     "to": SmartContractAddress,

                                     "value": "0x" + amountTosend.toString(16),

                                     "data": hashdata.events.Transfer.raw.data,

                                     "chainId": chainid
                                 };

                                 var privKey = new ethereumjs.Buffer.Buffer(privateKey, 'hex');

                                 let tx = new ethereumjs.Tx(rawTransaction);
                                 tx.sign(privKey)
                                 let serializedTx = tx.serialize();

                                 console.log('serializedTx:', serializedTx);

                                 web3provider.eth.sendSignedTransaction('0x' + serializedTx.toString('hex'), function(err, receipt) {
                                     if (!err) {
                                         console.log('success token sent to user: ' + receipt);
                                         alert('You have received your Tokens in your Wallet');
                                     } else {
                                         console.log('error: ' + err);
                                         alert("An error Occured: " + err);
                                     }
                                 });

})

On mobile wallets such as trust and metamask mobile connected with web3modal using wallet connect as provider, I successfully interacted with the wallet, prompt user to send BNB but

contractCall.send({ from: accountFrom, gas: 2000000 })

which is used to change the state of the smart contract to send user Bep20 token fails with Unknown account error after adding remote wallet to local using:

web3provider.eth.accounts.wallet.add(icoAccount);

Note: If I try skipping

contractCall.send({ from: accountFrom, gas: 2000000 })

and use contractCall.encodeABI() for data parameter, it works fine but no token is actually sent to the user and I guess is because the smart contact state needs to be changed/altered with

myContract.methods.myMethod([param1[, param2[, ...]]]).send

Please I need any useful help/tip to make this work on mobile wallet, I have been on this bug for a few days now, thanks

Body:
I finally fixed this error, and I will like to answer comprehensively for future visitors. The short answer will come first to implement the solution, and the long comprehensive answer afterward to help you understand better and learn the technicalities of fixing the bug

Note:  I am using walletconnect and web3modal under the hood for my DAPP on Mobile browser and Metamask for Desktop and I'm using vanilla javascript for web3 implemenation

Short Answer:
I had to set givenProvider to the currentProvider which was initialized on web3 instance and that was my RPC URL provider, for me my RPC URL provider is: https://getblock.io/ which was passed in walletconnect/web3modal provider options paramater

I'm connecting to BSC so my RPC URL is: https://bsc.getblock.io/mainnet/?api_key=API_KEY

You may use other RPC URL providers of your choice

So the givenProvider is set like this:

web3.givenProvider = web3.currentProvider;
web3.eth.givenProvider = web3.currentProvider;
web3.eth.accounts.givenProvider = web3.currentProvider;

read walletconnect docs on setting provider(s) here: https://docs.walletconnect.com/quick-start/dapps/web3-provider

Setting the web3.givenProvider to web3.currentProvider fixed the issue as web3.givenProvider was null

Long Answer:

You need to understand what is currentProvider and givenProvider are, as the bug resolves around the web3 provider.
In my understanding as of writting this answer givenProvider is the provider injected in an Ethereum enabled browser while currentProvider is the  provider that you passed in on the initialization of web3.

The error is: Unknown account

This problem doesn't appear on a desktop browser where metamask is installed because injects the givenProvider, except of course is a remote account that doesn't exist on the provider node

You have to add the account to the provider node using:

  var account=  web3provider.eth.accounts.privateKeyToAccount(PRIVATE_KEY);
var addAccount = web3provider.eth.accounts.wallet.add(account);

This solves the error on desktop browser without having to configure or set up much and that is because masks makes your browser Ethereum enabled and injects givenProvider

But for mobile browsers, you will face this issue because mobile browsers aren't Ethereum enabled environment. You will have to set givenProvider to a valid provider after initializing web3 through walletconenct.

Note: givenProvider talks to the blockchain through the web and it is null on mobile browsers. Console.log(web3) will show you the values of web3 instance

Putting all together your code should look like this:

import WalletConnectProvider from "@walletconnect/web3-provider";
import Web3 from "web3";

//  Create WalletConnect Provider
const provider = new WalletConnectProvider({
  rpc: {
    1: "https://mainnet.mycustomnode.com",
    3: "https://ropsten.mycustomnode.com",
    100: "https://dai.poa.network",
    // ...
  },
});

await provider.enable();

//  Create Web3 instance
const web3 = new Web3(provider);

//FIX STARTS HERE

//set givenProvider to currentProvider
 web3.givenProvider = web3.currentProvider;
 web3.eth.givenProvider = web3.currentProvider;
 web3.eth.accounts.givenProvider = web3.currentProvider;

//add wallet to provider node
var account= web3.eth.accounts.privateKeyToAccount(PRIVATE_KEY);
var addAccount = web3.eth.accounts.wallet.add(account);
var accountFrom = account.address;

var gas = contractCall.estimateGas({ from: accountFrom });
 gas.then(function(gasTouse) {
contractCall.send({
from: accountFrom, gas: gasTouse }).then(function(hashdata){
   console.log(hashdata);

});
});

Note: Be sure you estimate gas and include it, as without it you may encounter some gas-related errors.

Happy coding :)


问:
Execute a Response of a command in bash
In the following script the response of sed is

```<code>export SECRET_KEY= '321321
</code>```

I need to execute that response in the shell, exporting the value to SECRET_KEY i.e. echo $SECRET_KEY will give the exported key as 321321

```<code>aws-runas test >>test.txt
echo `sed -n -e 's/^.*\(\(export SECRET_KEY\).*\)/\1/p' test.txt`
</code>```

I've tried using eval, source <(echo $command). it gives the following error

sed: -e expression #1, char 13: unterminated `s' command

Is there a way to execute the response of sed as a command?

答:
You can just use sed:

`sed -n -e 's/^.*\(\(export SECRET_KEY\).*\)/\1/p' test.txt`
```
<p>Be careful, the export that you made doesn't work.</p>
<pre class="lang-sh prettyprint-override"><code>export SECRET_KEY= '321321'
export: not an identifier: 321321
</code>```

Use:

export SECRET_KEY=321321
```

Title: Execute a Response of a command in bash

Body:
In the following script the response of sed is

export SECRET_KEY= '321321

I need to execute that response in the shell, exporting the value to SECRET_KEY i.e. echo $SECRET_KEY will give the exported key as 321321

aws-runas test >>test.txt
echo `sed -n -e 's/^.*\(\(export SECRET_KEY\).*\)/\1/p' test.txt`

I've tried using eval, source <(echo $command). it gives the following error

sed: -e expression #1, char 13: unterminated `s' command

Is there a way to execute the response of sed as a command?

Body:
You can just use sed:

`sed -n -e 's/^.*\(\(export SECRET_KEY\).*\)/\1/p' test.txt`

Be careful, the export that you made doesn't work.

export SECRET_KEY= '321321'
export: not an identifier: 321321

Use:

export SECRET_KEY=321321


问:
Django - how to show a mathematic result as percentage in dango admin
I have created a model that have one field that calculate the percentage of a month profit, the result is a float number rounded to 2 decimals, for example 0.50

I would like to have in the admin list as percentage, for example. 0.50 would show as 50.00%, is that possíble, how can i achieve that?

my model:

```<code>class PortfolioToken(models.Model):
    total_today = models.FloatField()
    order_value = models.FloatField()
    token_price = models.FloatField()
    month_profit = models.FloatField(editable=False)

    def save(self, *args, **kwargs):
        if PortfolioToken.objects.exists():
            last = PortfolioToken.objects.latest('id')
            # month profit would show as percentage in admin
            self.month_profit = round((self.token_price - last.token_price)/last.token_price, 2)
        else
        ...

</code>```

My admin list

```<code>class PortfolioTokenAdmin(admin.ModelAdmin):
    list_display =('total_today', 'order_value', 'token_price', 'month_profit')
</code>```

答:
You can add it as a custom field:</p>
```<code>class PortfolioTokenAdmin(admin.ModelAdmin):
    fields = ('total_today', 'order_value', 'token_price', 'month_profit', 'percentage')
    readonly_fields = ('percentage',)

    def percentage(self, obj):
        # Return the month_profit as percentage string
        return str(format(float(obj.month_profit * 100), '.2f') + ' %')
</code>```

Body:
I have created a model that have one field that calculate the percentage of a month profit, the result is a float number rounded to 2 decimals, for example 0.50

I would like to have in the admin list as percentage, for example. 0.50 would show as 50.00%, is that possíble, how can i achieve that?

my model:

class PortfolioToken(models.Model):
    total_today = models.FloatField()
    order_value = models.FloatField()
    token_price = models.FloatField()
    month_profit = models.FloatField(editable=False)

    def save(self, *args, **kwargs):
        if PortfolioToken.objects.exists():
            last = PortfolioToken.objects.latest('id')
            # month profit would show as percentage in admin
            self.month_profit = round((self.token_price - last.token_price)/last.token_price, 2)
        else
        ...

My admin list

class PortfolioTokenAdmin(admin.ModelAdmin):
    list_display =('total_today', 'order_value', 'token_price', 'month_profit')

Body:
You can add it as a custom field:

class PortfolioTokenAdmin(admin.ModelAdmin):
    fields = ('total_today', 'order_value', 'token_price', 'month_profit', 'percentage')
    readonly_fields = ('percentage',)

    def percentage(self, obj):
        # Return the month_profit as percentage string
        return str(format(float(obj.month_profit * 100), '.2f') + ' %')


问:
ValueError at /modifier_produit/1 ModelForm has no model class specified
this is my forms.py :

```<code>class stockupdateform(forms.ModelForm):
    class Meta:
    model:stock
    fields =['categorie', 'nom', 'quantite']
</code>```

my views.py :

```<code> def list_nom(request):
      title='liste des produits'
      form =stockSearchForm(request.POST or None)
      queryset=stock.objects.all()
      context= {
     "title":title,
     "queryset":queryset,
     "form":form,
     }
     if request.method == 'POST':
     queryset = stock.objects.filter(categorie=form['categorie'].value(),
        nom=form['nom'].value())
     context= {
     "title":title,
     "queryset":queryset,
     "form":form,
       }
      return render(request, "list_nom.html",context)
</code>```

my list_nom.html :

```<code><table class='table'>
   <thead>
    <tr>
    <th>id</th>
    <th>categorie</th>
    <th>produit</th>
    <th>quantite</th>
     </tr>
    </thead>
   {% for instance in queryset %}
     <tr>
    <td>{{forloop.counter}}</td>
   <td>{{instance.categorie}}</td>
   <td><a href="{% url 'modifier_produit' instance.id  %}">{{instance.nom}} </a> </td>
    <td>{{instance.quantite}}</td>
   </tr>
   {% endfor %}
   </table>
</code>```

I have this probleme what i can do :
ValueError at /modifier_produit/1   ModelForm has no model class specified.

答:
You don't set variables with :, but with =. Assuming that you have stock as a class in models, you have to change your stockupdateform to that:

```<code>class stockupdateform(forms.ModelForm):
    class Meta:
        model = stock
        fields = ['categorie', 'nom', 'quantite']
</code>```

PS Please share code with exactly the same indentations as your code. It's important to share it that way, because we may think your indentations are not correct (this code would fall 100% cause of it).

Body:
this is my forms.py :

class stockupdateform(forms.ModelForm):
    class Meta:
    model:stock
    fields =['categorie', 'nom', 'quantite']

my views.py :

 def list_nom(request):
      title='liste des produits'
      form =stockSearchForm(request.POST or None)
      queryset=stock.objects.all()
      context= {
     "title":title,
     "queryset":queryset,
     "form":form,
     }
     if request.method == 'POST':
     queryset = stock.objects.filter(categorie=form['categorie'].value(),
        nom=form['nom'].value())
     context= {
     "title":title,
     "queryset":queryset,
     "form":form,
       }
      return render(request, "list_nom.html",context)

my list_nom.html :

    id
    categorie
    produit
    quantite

   {% for instance in queryset %}

    {{forloop.counter}}
   {{instance.categorie}}
   {{instance.nom}}
    {{instance.quantite}}

   {% endfor %}

I have this probleme what i can do :
ValueError at /modifier_produit/1   ModelForm has no model class specified.

Body:
You don't set variables with :, but with =. Assuming that you have stock as a class in models, you have to change your stockupdateform to that:

class stockupdateform(forms.ModelForm):
    class Meta:
        model = stock
        fields = ['categorie', 'nom', 'quantite']

PS Please share code with exactly the same indentations as your code. It's important to share it that way, because we may think your indentations are not correct (this code would fall 100% cause of it).


问:
Flutter Keyboard hide textField in nested Listviews
I am making a cross platform app using Flutter with a responsive layout. I'll describe the problem using the login page layout. The layout is divided into 3 widgets (Desktop, Tablet, Mobile) each of which has a ListView with its graphic components, images, text etc ... Inside this ListView the 3 widgets share the Login Form another ListView with its components (text fields, buttons ...)

The problem: when opened the keyboard does not scroll the text fields covering them

Below is a draft of the code:

```<code>//The form shared by the 3 Widgets
class SignInFrom extends StatelessWidget {
  const SignInFrom({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Form(
      child: ListView(
        shrinkWrap: true,
        physics: const ClampingScrollPhysics(),
        children: [
          //COMPONENTS
        ],
      ),
    );
  }
}
</code>```

This is one of the 3 widgets (Mobile):

```<code>class SignInPageMobile extends StatelessWidget {
  const SignInPageMobile({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: ListView(
        children: [

          /* COMPONENTS
           *  ...
           */

          const SignInForm(), //The above SignInFrom widget
        ],
      ),
    );
  }
}
</code>```

The SignInPage widget:

```<code>class SignInPage extends StatelessWidget {
  const SignInPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      body: BlocProvider(
        create: (context) => getIt<SignInFormBloc>(),
        child: Responsive(
          mobile: SignInPageMobile(),
          tablet: SignInPageTablet(),
          desktop: SignInPageDesktop(),
        ),
      ),
    );
  }
}
</code>```

Edit

I want to mention that in the Scaffold that will contain one of the 3 widgets it is set:
resizeToAvoidBottomInset: false

Because my components are built on dynamic values of height and width using flutter_screenutil based on the sacaffold size so it needs to keep its dimensions even when the keyboard is open

答:
You try

```<code>Padding(
       padding: EdgeInsets.only(top: 8, left: 8, right: 8,bottom:     MediaQuery.of(context).viewInsets.bottom))
</code>```

Body:
I am making a cross platform app using Flutter with a responsive layout. I'll describe the problem using the login page layout. The layout is divided into 3 widgets (Desktop, Tablet, Mobile) each of which has a ListView with its graphic components, images, text etc ... Inside this ListView the 3 widgets share the Login Form another ListView with its components (text fields, buttons ...)

The problem: when opened the keyboard does not scroll the text fields covering them

Below is a draft of the code:

//The form shared by the 3 Widgets
class SignInFrom extends StatelessWidget {
  const SignInFrom({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Form(
      child: ListView(
        shrinkWrap: true,
        physics: const ClampingScrollPhysics(),
        children: [
          //COMPONENTS
        ],
      ),
    );
  }
}

This is one of the 3 widgets (Mobile):

class SignInPageMobile extends StatelessWidget {
  const SignInPageMobile({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: ListView(
        children: [

          /* COMPONENTS
           *  ...
           */

          const SignInForm(), //The above SignInFrom widget
        ],
      ),
    );
  }
}

The SignInPage widget:

class SignInPage extends StatelessWidget {
  const SignInPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      body: BlocProvider(
        create: (context) => getIt<SignInFormBloc>(),
        child: Responsive(
          mobile: SignInPageMobile(),
          tablet: SignInPageTablet(),
          desktop: SignInPageDesktop(),
        ),
      ),
    );
  }
}

Edit

I want to mention that in the Scaffold that will contain one of the 3 widgets it is set:
resizeToAvoidBottomInset: false

Because my components are built on dynamic values of height and width using flutter_screenutil based on the sacaffold size so it needs to keep its dimensions even when the keyboard is open

Body:
You try

Padding(
       padding: EdgeInsets.only(top: 8, left: 8, right: 8,bottom:     MediaQuery.of(context).viewInsets.bottom))


问:
ExpressJS Await not working - SQL SELECT too fast (before INSERT)
I want to make a SQL Insert and after that a Select with the complete List to show in Vue inclusive the new entry. But the Select is faster than the Insert and does only return the old values which are already in the Table. I tried with setTimeout and Async-Await. (SQL Statements are working)

Can someone help me i am new into JS.

```<code>async function select_time(datum, mitarbeiter_id){
    let returnQuery = 'SELECT ...'
    let retquery = mysql.format(returnQuery,[datum, mitarbeiter_id]);
    pool.query(retquery,(err, data) => {
        if(err) {
            console.error(err);
            return err
        }

        return data
    });
}

async function insert_time(datum, mitarbeiter_id, projekt_id, zeit_von, zeit_bis, stunden, taetigkeit){

    let selectQuery = 'INSERT INTO ...';
    let query = mysql.format(selectQuery,[taetigkeit, projekt_id, mitarbeiter_id, zeit_von, zeit_bis, stunden, datum]);
    pool.query(query,(err) => {
        if(err) {
            console.error(err);
        }
    });
    if(taetigkeit == 15){
        let updateQuery = "UPDATE ..."
        let query2 = mysql.format(updateQuery, [mitarbeiter_id])
        pool.query(query2,(err, data) => {
        if(err) {
            console.error(err);
        }
        });
    }
}

async function run_insert_time(datum, mitarbeiter_id, projekt_id, zeit_von, zeit_bis, stunden, taetigkeit){
    await insert_time(datum, mitarbeiter_id, projekt_id, zeit_von, zeit_bis, stunden, taetigkeit)
    const jsret = await select_time(datum, mitarbeiter_id)
    return jsret
}

app.get('/insertTime', (req, res) => {
    const datum = req.query.datum;
    const mitarbeiter_id = req.query.mitarbeiter_id;
    let projekt_id = req.query.projekt_id;
    let zeit_von = req.query.zeit_von;
    let zeit_bis = req.query.zeit_bis;
    const stunden = req.query.stunden;
    const taetigkeit = req.query.taetigkeit;

    const js = run_insert_time(datum, mitarbeiter_id, projekt_id, zeit_von, zeit_bis, stunden, taetigkeit)

    res.json(js)
 })
</code>```

答:
To expand on @anatoly's very good answer:

I find the inline return new Promise... to be visually disruptive of the program flow. By creating a separate "promisified" version, your async function becomes much cleaner. It's just rearranging the code, with the same ultimate outcome.

```<code>const pQuery = qryText => new Promise((resolve, reject) => {
  pool.query(qryText, (err, data) => {
    if (err) reject(err);
    else resolve(data);
  });
});
</code>```

Then your async functions become quite clean. For example:

```<code>async function select_time(datum, mitarbeiter_id){
  let returnQuery = 'SELECT ...'
  let retquery = mysql.format(returnQuery,[datum, mitarbeiter_id]);
  const data = await pQuery(retquery);
  return data;
}
</code>```

Aside: node.js has util.promisify, which makes this even easier to implement.

```<code>const { promisify } = require('util');
const pQuery = promisify(pool.query.bind(pool));
</code>```

(Pretty sure you need the bind, but you could try without and see if it works)

Body:
I want to make a SQL Insert and after that a Select with the complete List to show in Vue inclusive the new entry. But the Select is faster than the Insert and does only return the old values which are already in the Table. I tried with setTimeout and Async-Await. (SQL Statements are working)

Can someone help me i am new into JS.

async function select_time(datum, mitarbeiter_id){
    let returnQuery = 'SELECT ...'
    let retquery = mysql.format(returnQuery,[datum, mitarbeiter_id]);
    pool.query(retquery,(err, data) => {
        if(err) {
            console.error(err);
            return err
        }

        return data
    });
}

async function insert_time(datum, mitarbeiter_id, projekt_id, zeit_von, zeit_bis, stunden, taetigkeit){

    let selectQuery = 'INSERT INTO ...';
    let query = mysql.format(selectQuery,[taetigkeit, projekt_id, mitarbeiter_id, zeit_von, zeit_bis, stunden, datum]);
    pool.query(query,(err) => {
        if(err) {
            console.error(err);
        }
    });
    if(taetigkeit == 15){
        let updateQuery = "UPDATE ..."
        let query2 = mysql.format(updateQuery, [mitarbeiter_id])
        pool.query(query2,(err, data) => {
        if(err) {
            console.error(err);
        }
        });
    }
}

async function run_insert_time(datum, mitarbeiter_id, projekt_id, zeit_von, zeit_bis, stunden, taetigkeit){
    await insert_time(datum, mitarbeiter_id, projekt_id, zeit_von, zeit_bis, stunden, taetigkeit)
    const jsret = await select_time(datum, mitarbeiter_id)
    return jsret
}

app.get('/insertTime', (req, res) => {
    const datum = req.query.datum;
    const mitarbeiter_id = req.query.mitarbeiter_id;
    let projekt_id = req.query.projekt_id;
    let zeit_von = req.query.zeit_von;
    let zeit_bis = req.query.zeit_bis;
    const stunden = req.query.stunden;
    const taetigkeit = req.query.taetigkeit;

    const js = run_insert_time(datum, mitarbeiter_id, projekt_id, zeit_von, zeit_bis, stunden, taetigkeit)

    res.json(js)
 })

Body:
To expand on @anatoly's very good answer:

I find the inline return new Promise... to be visually disruptive of the program flow. By creating a separate "promisified" version, your async function becomes much cleaner. It's just rearranging the code, with the same ultimate outcome.

const pQuery = qryText => new Promise((resolve, reject) => {
  pool.query(qryText, (err, data) => {
    if (err) reject(err);
    else resolve(data);
  });
});

Then your async functions become quite clean. For example:

async function select_time(datum, mitarbeiter_id){
  let returnQuery = 'SELECT ...'
  let retquery = mysql.format(returnQuery,[datum, mitarbeiter_id]);
  const data = await pQuery(retquery);
  return data;
}

Aside: node.js has util.promisify, which makes this even easier to implement.

const { promisify } = require('util');
const pQuery = promisify(pool.query.bind(pool));

(Pretty sure you need the bind, but you could try without and see if it works)


问:
Get some data from a htm page and save in mysql
I am not a programmer :(

I would like a page where I insert the address from another x.htm page and click "get"

Then I want to save the data in a mysql database, so I can get the data out for each driver.

Statistik: 07-02-2022 21:55:35 -

          Pos

          driver

          Car

           1-Red

           2-White

           3-Blue

           4-Yellow

          Best time

          Total laps

          1

          James Hunt

          Alfa Romeo GTA

          7.952

          7.963

          7.975

          8.088

          7.952

          88.25

          2

          Jackie Stewart

          Mini Cooper

          8.176

          8.194

          7.989

          8.197

          7.989

          86.68

```

答:
Well, man, this is super easy: you can use QuerySelectorAll.

See this example based on you code:

const rows = [];
document.querySelectorAll('table tbody tr').forEach((tr, rowIndex) => {
    const row = [];
    tr.querySelectorAll('td').forEach((item, cellIndex) => {
      console.log(`row ${rowIndex}, cell ${cellIndex}:`, item.textContent.trim());
      row.push(item.textContent.trim());
    });
    rows.push(row);
});
console.log("rows", rows); // you can use this data to save on you database```
<pre class="snippet-code-html lang-html prettyprint-override"><code><table>
   <tbody>
      <center>
         <b>
            <p>Statistik: 07-02-2022 21:55:35 -  </p>
         </b>
      </center>
      <br />
      <tr bgColor="#999999">
         <td bgcolor="#999999" width="30">
            <div align="center"> <font face="Verdana">Pos </font></div>
         </td>
         <td bgcolor="#999999" width="158">
            <div align="center"> <font face="Verdana">driver </font></div>
         </td>
         <td bgcolor="#999999" width="100">
            <div align="center"> <font face="Verdana">Car </font></div>
         </td>
         <td bgcolor="#e5665e" width="70">
            <div align="center"> <font face="Verdana"> 1-Red</font></div>
         </td>
         <td bgcolor="#ffffff" width="70">
            <div align="center"> <font face="Verdana"> 2-White</font></div>
         </td>
         <td bgcolor="#78ccea" width="70">
            <div align="center"> <font face="Verdana"> 3-Blue</font></div>
         </td>
         <td bgcolor="#ffff28" width="70">
            <div align="center"> <font face="Verdana"> 4-Yellow</font></div>
         </td>
         <td bgcolor="#999999" width="70">
            <div align="center"> <font face="Verdana"><b>Best time</b></font></div>
         </td>
         <td bgcolor="#999999" width="80">
            <div align="center"> <font face="Verdana">Total laps</font></div>
         </td>
      </tr>
      <tr bgColor="#999999">
         <td bgcolor="#ffffff" width="30">
            <div align="center"> <font face="Verdana">1</font></div>
         </td>
         <td bgcolor="#ffffff" width="158">
            <div align="center"> <font face="Verdana">James Hunt</font></div>
         </td>
         <td bgcolor="#ffffff" width="100">
            <div align="center"> <font face="Verdana">Alfa Romeo GTA</font></div>
         </td>
         <td bgcolor="#87fe58" width="70">
            <div align="center"> <font face="Verdana"><b>7.952</b></font></div>
         </td>
         <td bgcolor="#87fe58" width="70">
            <div align="center"> <font face="Verdana"><b>7.963</b></font></div>
         </td>
         <td bgcolor="#87fe58" width="70">
            <div align="center"> <font face="Verdana"><b>7.975</b></font></div>
         </td>
         <td bgcolor="#87fe58" width="70">
            <div align="center"> <font face="Verdana"><b>8.088</b></font></div>
         </td>
         <td bgcolor="#ffffff" width="70">
            <div align="center"> <font face="Verdana"><b>7.952</b></font></div>
         </td>
         <td bgcolor="#ffffff" width="80">
            <div align="center"> <font face="Verdana"><b>88.25</b></font></div>
         </td>
      </tr>
      <tr bgColor="#999999">
         <td bgcolor="#ffffff" width="30">
            <div align="center"> <font face="Verdana">2</font></div>
         </td>
         <td bgcolor="#ffffff" width="158">
            <div align="center"> <font face="Verdana">Jackie Stewart</font></div>
         </td>
         <td bgcolor="#ffffff" width="100">
            <div align="center"> <font face="Verdana">Mini Cooper</font></div>
         </td>
         <td bgcolor="#b6fea6" width="70">
            <div align="center"> <font face="Verdana">8.176</font></div>
         </td>
         <td bgcolor="#b6fea6" width="70">
            <div align="center"> <font face="Verdana">8.194</font></div>
         </td>
         <td bgcolor="#b6fea6" width="70">
            <div align="center"> <font face="Verdana">7.989</font></div>
         </td>
         <td bgcolor="#b6fea6" width="70">
            <div align="center"> <font face="Verdana">8.197</font></div>
         </td>
         <td bgcolor="#ffffff" width="70">
            <div align="center"> <font face="Verdana">7.989</font></div>
         </td>
         <td bgcolor="#ffffff" width="80">
            <div align="center"> <font face="Verdana">86.68</font></div>
         </td>
      </tr>
   </tbody>
</table></code>```

PS: if you using NodeJS(serverside) maybe you can get the HTML code
first to then use a dom reader like jsdom to parse HTML and use
the similar previous solution.

PS 2: you can use axios to handle http/s requests

```<code>const html = (await axios.get("https://example.com/page.html")).data;
const dom = new JSDOM(html);
const trs = dom.querySelectorAll('table tbody tr');
</code>```

Body:
Well, man, this is super easy: you can use QuerySelectorAll.

See this example based on you code:

const rows = [];
document.querySelectorAll('table tbody tr').forEach((tr, rowIndex) => {
    const row = [];
    tr.querySelectorAll('td').forEach((item, cellIndex) => {
      console.log(`row ${rowIndex}, cell ${cellIndex}:`, item.textContent.trim());
      row.push(item.textContent.trim());
    });
    rows.push(row);
});
console.log("rows", rows); // you can use this data to save on you database

<table>
   <tbody>
      <center>
         <b>
            <p>Statistik: 07-02-2022 21:55:35 -  </p>
         </b>
      </center>
      <br />
      <tr bgColor="#999999">
         <td bgcolor="#999999" width="30">
            <div align="center"> <font face="Verdana">Pos </font></div>
         </td>
         <td bgcolor="#999999" width="158">
            <div align="center"> <font face="Verdana">driver </font></div>
         </td>
         <td bgcolor="#999999" width="100">
            <div align="center"> <font face="Verdana">Car </font></div>
         </td>
         <td bgcolor="#e5665e" width="70">
            <div align="center"> <font face="Verdana"> 1-Red</font></div>
         </td>
         <td bgcolor="#ffffff" width="70">
            <div align="center"> <font face="Verdana"> 2-White</font></div>
         </td>
         <td bgcolor="#78ccea" width="70">
            <div align="center"> <font face="Verdana"> 3-Blue</font></div>
         </td>
         <td bgcolor="#ffff28" width="70">
            <div align="center"> <font face="Verdana"> 4-Yellow</font></div>
         </td>
         <td bgcolor="#999999" width="70">
            <div align="center"> <font face="Verdana"><b>Best time</b></font></div>
         </td>
         <td bgcolor="#999999" width="80">
            <div align="center"> <font face="Verdana">Total laps</font></div>
         </td>
      </tr>
      <tr bgColor="#999999">
         <td bgcolor="#ffffff" width="30">
            <div align="center"> <font face="Verdana">1</font></div>
         </td>
         <td bgcolor="#ffffff" width="158">
            <div align="center"> <font face="Verdana">James Hunt</font></div>
         </td>
         <td bgcolor="#ffffff" width="100">
            <div align="center"> <font face="Verdana">Alfa Romeo GTA</font></div>
         </td>
         <td bgcolor="#87fe58" width="70">
            <div align="center"> <font face="Verdana"><b>7.952</b></font></div>
         </td>
         <td bgcolor="#87fe58" width="70">
            <div align="center"> <font face="Verdana"><b>7.963</b></font></div>
         </td>
         <td bgcolor="#87fe58" width="70">
            <div align="center"> <font face="Verdana"><b>7.975</b></font></div>
         </td>
         <td bgcolor="#87fe58" width="70">
            <div align="center"> <font face="Verdana"><b>8.088</b></font></div>
         </td>
         <td bgcolor="#ffffff" width="70">
            <div align="center"> <font face="Verdana"><b>7.952</b></font></div>
         </td>
         <td bgcolor="#ffffff" width="80">
            <div align="center"> <font face="Verdana"><b>88.25</b></font></div>
         </td>
      </tr>
      <tr bgColor="#999999">
         <td bgcolor="#ffffff" width="30">
            <div align="center"> <font face="Verdana">2</font></div>
         </td>
         <td bgcolor="#ffffff" width="158">
            <div align="center"> <font face="Verdana">Jackie Stewart</font></div>
         </td>
         <td bgcolor="#ffffff" width="100">
            <div align="center"> <font face="Verdana">Mini Cooper</font></div>
         </td>
         <td bgcolor="#b6fea6" width="70">
            <div align="center"> <font face="Verdana">8.176</font></div>
         </td>
         <td bgcolor="#b6fea6" width="70">
            <div align="center"> <font face="Verdana">8.194</font></div>
         </td>
         <td bgcolor="#b6fea6" width="70">
            <div align="center"> <font face="Verdana">7.989</font></div>
         </td>
         <td bgcolor="#b6fea6" width="70">
            <div align="center"> <font face="Verdana">8.197</font></div>
         </td>
         <td bgcolor="#ffffff" width="70">
            <div align="center"> <font face="Verdana">7.989</font></div>
         </td>
         <td bgcolor="#ffffff" width="80">
            <div align="center"> <font face="Verdana">86.68</font></div>
         </td>
      </tr>
   </tbody>
</table>

PS: if you using NodeJS(serverside) maybe you can get the HTML code
first to then use a dom reader like jsdom to parse HTML and use
the similar previous solution.

PS 2: you can use axios to handle http/s requests

const html = (await axios.get("https://example.com/page.html")).data;
const dom = new JSDOM(html);
const trs = dom.querySelectorAll('table tbody tr');


问:
Tools to compare two sites structures
Does anyone knows about any tools allowing to compare two almost exactly same websites?

Simply, I have a sandbox site and production site, and would like to find out the difference between them, to know what content to move to production site.

Thanks!

Edit:

Ok, I see I missed a critical piece of information (sorry!). The both sites are online and based on CMS (Drupal), hence I need some crawling tool which would run over the two sites, and show what pages present in sandbox, but not on production.

Thanks for everyone who answered regardless!

答:
As sunny said, use a crawler and a diff tool.

For the crawler I'd prefer httrack over wget.
Many sites use images referenced from css nowadays.
wget was not able to load files referenced from css when I last checked.
Besides that it has a nice GUI.

As of the diff tool:
I use FileSync since the Windows 3.1 days.
There are certainly more fancy diff tools but this one is lean and clean an does the job.
On unix you can always do diff -r.
If you have eclipse on your machine it has a nice diff viewer which can compare two directories as well.

OwnerDisplayName: SyRenity

ContentLicense: CC BY-SA 2.5

Title: Tools to compare two sites structures

LastEditorDisplayName: SyRenity


问:
Updating image source on scroll using pure javascript
I'm trying to make a component that updates its source image on scroll when it gets referenced in its div tag ' infoBG 'in my main component. The function seems to work but I guess the return statement is overriding the function and just returns the original image without updating. What's the right way to do this so the function updates the first returned image?</p>
```<code>
function Infoimg () {

  window.addEventListener("scroll", event => {
    var scrollValue = window.scrollY;
    var image = document.getElementById('infoBG');
    if (scrollValue>100){
      image.setAttribute = ('src','images/ccpLogo.svg');
    }else{
      image.setAttribute = ('src','images/Passport Stock Photo.svg');
    }
    console.log(image)
    console.log(scrollValue);
  });

 return(

 <img src={'images/Passport Stock Photo.svg'} alt='Info-Background'/>

 )

}

</code>```

答:
You basically need to use useRef, which could be better for performance. Remember that useState will trigger a re-render. But in fact, you just need to update the source of your image. I would use something like this.

```<code>import { useCallback, useEffect, useRef } from "react";

import "./styles.css";

export default function App() {
  const imgRef = useRef();
  const middleRef = useRef();

  const onScroll = useCallback(() => {
    if (imgRef != null) {
      var scrollValue = window.scrollY;
      if (scrollValue > 100) {
        imgRef.current.src = "https://picsum.photos/id/237/200/300";
      } else {
        imgRef.current.src = "https://picsum.photos/seed/picsum/200/300";
      }

      console.log(scrollValue);
    }
  }, []);

  useEffect(() => {
    window.addEventListener("scroll", onScroll, true);
    return () => {
      window.removeEventListener("scroll", onScroll, true);
    };
  }, [onScroll]);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>

      <div ref={middleRef} className="middle" />
      <img
        ref={imgRef}
        src={"https://picsum.photos/seed/picsum/200/300"}
        alt="Info-Background"
      />
    </div>
  );
}
</code>```

Here is the link. You can check it working on codesandbox.
https://codesandbox.io/s/ecstatic-https-hzi5n

Body:
I'm trying to make a component that updates its source image on scroll when it gets referenced in its div tag ' infoBG 'in my main component. The function seems to work but I guess the return statement is overriding the function and just returns the original image without updating. What's the right way to do this so the function updates the first returned image?

function Infoimg () {

  window.addEventListener("scroll", event => {
    var scrollValue = window.scrollY;
    var image = document.getElementById('infoBG');
    if (scrollValue>100){
      image.setAttribute = ('src','images/ccpLogo.svg');
    }else{
      image.setAttribute = ('src','images/Passport Stock Photo.svg');
    }
    console.log(image)
    console.log(scrollValue);
  });

 return(

 )

}

Body:
You basically need to use useRef, which could be better for performance. Remember that useState will trigger a re-render. But in fact, you just need to update the source of your image. I would use something like this.

import { useCallback, useEffect, useRef } from "react";

import "./styles.css";

export default function App() {
  const imgRef = useRef();
  const middleRef = useRef();

  const onScroll = useCallback(() => {
    if (imgRef != null) {
      var scrollValue = window.scrollY;
      if (scrollValue > 100) {
        imgRef.current.src = "https://picsum.photos/id/237/200/300";
      } else {
        imgRef.current.src = "https://picsum.photos/seed/picsum/200/300";
      }

      console.log(scrollValue);
    }
  }, []);

  useEffect(() => {
    window.addEventListener("scroll", onScroll, true);
    return () => {
      window.removeEventListener("scroll", onScroll, true);
    };
  }, [onScroll]);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>

      <div ref={middleRef} className="middle" />
      <img
        ref={imgRef}
        src={"https://picsum.photos/seed/picsum/200/300"}
        alt="Info-Background"
      />
    </div>
  );
}

Here is the link. You can check it working on codesandbox.
https://codesandbox.io/s/ecstatic-https-hzi5n


问:
How can I autopopulate selection list in javascript?
I would like to auto populate my HTML table with drop down list.

I used below code, but the problem is, I need to specify 24 option to this drop down list, and if I would like add all 24, this line will be extremly long.

Can I ask if there is any way to solve it a bit shorter code and better way?

List:

AC Propulsion

Ajax

AM General

Ambassador

AMC

American

American Underslung

Anteros Coachworks

Apollo

Apperson

Arnolt

Auburn

Aurica Motors

Avanti

Brewster

Brisco

Brush

BXR

Carroll Shelby

Case

Chadwick

Chandler

Checker

Comet

```<code>row2.insertCell(count + 1).innerHTML = '<select id="' + count2 + '"' + 'name="cars"><option value="volvo">Volvo</option><option value="saab">Saab</option></select>'
</code>```

答:
As others have mentioned, but with a working example, I would put cars in an array. I've also used option text to generate option value, so you don't have to enter values into array.

const options = ['AC Propulsion', 'Ajax', 'AM General', 'Ambassador', 'AMC', 'American', 'American Underslung', 'Anteros Coachworks',
    'Apollo', 'Apperson', 'Arnolt', 'Auburn', 'Aurica Motors', 'Avanti', 'Brewster', 'Brisco', 'Brush', 'BXR', 'Carroll Shelby',
    'Case', 'Chadwick', 'Chandler', 'Checker', 'Comet'];

const optionsHtml = () => {
    let result = '';
    let optionValue = '';
    options.forEach(optionText => {
      optionValue = optionText.replace(/ /g, '-').toLowerCase();
      result += `<option value="${optionValue}">${optionText}</option>\n`;
    });
    return result;
}

const row2 = {
    insertCell(count) {
        const tr = document.createElement('tr');
        const td = document.createElement('td');
        td.classList.add(`td-${count}`);
        tr.appendChild(td);
        document.getElementById('test-table').appendChild(tr);
        return td;
    }
}

const count = 0;
const count2 = 1;

row2.insertCell(count + 1).innerHTML = '<select id="' + count2 + '"' + 'name="cars">' + optionsHtml() + '</select>'```
<pre class="snippet-code-html lang-html prettyprint-override"><code><table id="test-table">
    <thead>
        <tr>
            <th>
                Car
           </th>
    </thead>
    <tbody>
    </tbody>
</table></code>```

Body:
I would like to auto populate my HTML table with drop down list.

I used below code, but the problem is, I need to specify 24 option to this drop down list, and if I would like add all 24, this line will be extremly long.

Can I ask if there is any way to solve it a bit shorter code and better way?

List:

AC Propulsion

Ajax

AM General

Ambassador

AMC

American

American Underslung

Anteros Coachworks

Apollo

Apperson

Arnolt

Auburn

Aurica Motors

Avanti

Brewster

Brisco

Brush

BXR

Carroll Shelby

Case

Chadwick

Chandler

Checker

Comet

row2.insertCell(count + 1).innerHTML = '<select id="' + count2 + '"' + 'name="cars"><option value="volvo">Volvo</option><option value="saab">Saab</option></select>'

Body:
As others have mentioned, but with a working example, I would put cars in an array. I've also used option text to generate option value, so you don't have to enter values into array.

const options = ['AC Propulsion', 'Ajax', 'AM General', 'Ambassador', 'AMC', 'American', 'American Underslung', 'Anteros Coachworks',
    'Apollo', 'Apperson', 'Arnolt', 'Auburn', 'Aurica Motors', 'Avanti', 'Brewster', 'Brisco', 'Brush', 'BXR', 'Carroll Shelby',
    'Case', 'Chadwick', 'Chandler', 'Checker', 'Comet'];

const optionsHtml = () => {
    let result = '';
    let optionValue = '';
    options.forEach(optionText => {
      optionValue = optionText.replace(/ /g, '-').toLowerCase();
      result += `<option value="${optionValue}">${optionText}</option>\n`;
    });
    return result;
}

const row2 = {
    insertCell(count) {
        const tr = document.createElement('tr');
        const td = document.createElement('td');
        td.classList.add(`td-${count}`);
        tr.appendChild(td);
        document.getElementById('test-table').appendChild(tr);
        return td;
    }
}

const count = 0;
const count2 = 1;

row2.insertCell(count + 1).innerHTML = '<select id="' + count2 + '"' + 'name="cars">' + optionsHtml() + '</select>'

<table id="test-table">
    <thead>
        <tr>
            <th>
                Car
           </th>
    </thead>
    <tbody>
    </tbody>
</table>


问:
Access VBA: AutoExec macro can't find function?
I'm trying to execute a function that opens forms at startup and I created the AutoExec macro.

I have a module called startup in which there is a function called startup.

The AutoExec macro has the action Run Code with a function named startup ().

When I start my database, I get the error, "The expression you entered has a function that Access can't find".

Is there something I'm doing wrong?
Please help!

Thanks.

答:
You can't have the function name the same as the module name.
Change the function name from startup() to onStart().


问:
What is validation set for yolov5 training and is it necessary?
I'm training a yolov5 model and I have a dataset but I couldn't understand the differences between validation and test data. Should I split my dataset to train/test/val or just train/test?</p>

答: The validation dataset provides an unbiased assessment of a fitted model on the training dataset while fitting the model's hyper-parameters (e.g. the number of hidden units - layers and layer widths - in a neural network). Validation datasets can be used for early stop regularization (stopping training when the error in the validation dataset increases, as this is a sign of overfitting to the training dataset)


问:
How to iterate through an array starting from the last element? (Ruby)
I came with below solution but I believe that must be nicer one out there ...  </p>

```<code>array = [ 'first','middle','last']

index = array.length
array.length.times { index -= 1; puts array[index]}
</code>```

答:
You can use "unshift" method to iterate and add items to new "reversed" array.
Unshift will add a new item to the beginning of an array.
While << - adding in the end of an array. Thats why unshift here is good.

```<code>array = [ 'first','middle','last']
output = []
                             # or:
for item in array            #     array.each do |item|
  output.unshift(item)       #       output.unshift(item)
end                          #     end

puts "Reversed array: #{output}"
</code>```

will print: ["last", "middle", "first"]

Body:
I came with below solution but I believe that must be nicer one out there ...

array = [ 'first','middle','last']

index = array.length
array.length.times { index -= 1; puts array[index]}

Body:
You can use "unshift" method to iterate and add items to new "reversed" array.
Unshift will add a new item to the beginning of an array.
While << - adding in the end of an array. Thats why unshift here is good.

array = [ 'first','middle','last']
output = []
                             # or:
for item in array            #     array.each do |item|
  output.unshift(item)       #       output.unshift(item)
end                          #     end

puts "Reversed array: #{output}"

will print: ["last", "middle", "first"]


问:
How to automatically transform columns into objects in R?
I need that each column of my dataset become an object named with that column's name and containing its values as the object value.

I know how to do the process manually (see "Process question" heading below), but I need to automatize and generalize the process with as few rows as possible.

Example data

```<code>library(tibble)
df <- tibble(a = 1, b = 2, c = 3, d = 4)
</code>```

Input

```<code>> df
# A tibble: 1 x 4
      a     b     c     d
  <dbl> <dbl> <dbl> <dbl>
1     1     2     3     4

</code>```

Process Question

How to automatize this part?

```<code>a <- df$a
b <- df$b
c <- df$c
d <- df$d
</code>```

Output

```<code>> a;b;c;d
[1] 1
[1] 2
[1] 3
[1] 4
</code>```

答:
tibble/data.frame are list.  So, we can use list2env (or use attach)

```<code>list2env(df, .GlobalEnv)
</code>```

-checking

```<code>> a
[1] 1
> b
[1] 2
</code>```

Body:
I need that each column of my dataset become an object named with that column's name and containing its values as the object value.

I know how to do the process manually (see "Process question" heading below), but I need to automatize and generalize the process with as few rows as possible.

Example data

library(tibble)
df <- tibble(a = 1, b = 2, c = 3, d = 4)

Input

> df
# A tibble: 1 x 4
      a     b     c     d
  <dbl> <dbl> <dbl> <dbl>
1     1     2     3     4

Process Question

How to automatize this part?

a <- df$a
b <- df$b
c <- df$c
d <- df$d

Output

> a;b;c;d
[1] 1
[1] 2
[1] 3
[1] 4

Body:
tibble/data.frame are list.  So, we can use list2env (or use attach)

list2env(df, .GlobalEnv)

-checking

> a
[1] 1
> b
[1] 2