Skip to content
Allow Copyleaks API users to view the plagiarism report using their downloaded data. Using this report allows users to view the report anytime without being restricted by the Copyleaks expiration policy (that deletes the reports data).
TypeScript HTML CSS JavaScript
Branch: master
Clone or download
Latest commit 27990dc Jan 1, 2020
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.github/ISSUE_TEMPLATE Update issue templates Jan 1, 2020
client version bump Jan 1, 2020
server refactor back to old contentMode Nov 6, 2019
LICENSE remove LICENSE file extension Oct 15, 2019
README.md update readme Dec 17, 2019
plagiarism-report.code-workspace remove prettier settings from workspace Nov 13, 2019

README.md

Copyleaks plagiarism report

npm:badge

This allows you to view Copyleaks plagiarism report on your website. The report is based on Copyleaks scan results you downloaded via Copyleaks API. By using this component you can view the report anytime without being restricted by the Copyleaks expiration policy and control access policy to the information for your users.

Live demo

demo:img

Requirements

  • You should have a Copyleaks account and be able to complete a successful scan and store the results on your end
  • Server side application with access to stored Copyleaks reports
  • A web application with Angular version 8.x

Integration

You must use this module with data generated by Copyleaks API. In general these are the steps you should follow:

  1. Create an account on Copyleaks
  2. Use Copyleaks API to scan for plagiarism
  3. Store the data received from Completed Webhook on your server / cloud
  4. Download and store the source, pdf report (optional) and results on your server / cloud
  5. Create http endpoints to access the stored data (completed, source, pdf-report, results)
  6. Present the data in your website via Copyleaks plagiarism report

Installation

Install using npm

npm i @copyleaks/plagiarism-report

This library uses @angular/material and @angular/flex-layout as peer dependencies. If they are not already installed on your project, add them.

  • ng add @angular/material or npm i @angular/material
  • npm i @angular/flex-layout

Usage

Note: Copyleaks plagiarism report is built to work with data received from Copyleaks API. The responsibility for storing the data and serving it is in your hands.

Add CopyleaksReportModule to your module's imports

//...
import { CopyleaksReportModule } from "@copyleaks/plagiarism-report";

@NgModule({
  declarations: [AppComponent],
  imports: [
    // ...
    CopyleaksReportModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {}

Add the component to your template

<cr-copyleaks-report> </cr-copyleaks-report>

Inject CopyleaksService to your Component

export class SomeComponent {
  constructor(private copyleaksService: CopyleaksService, private http: HttpClient) {
    //...
  }
}

Basic usage

Note: This example assumes you have already downloaded and stored the data generated by copyleaks API

The component must be provided with the data generated by Copyleaks API. As mentioned above, your server must store that data, so your front end could access it via http requests. That means your server should support serving the following data:

  • Endpoint to get the Complete Result of a scan by scan id
  • Endpoint to get the Source of a scan by scan id
  • Endpoint to get a specific Result of a scan by scan id and a result id
  • (optional) Endpoint to download the Pdf of a scan by scan id

Example for the endpoints mentioned above:

  • yourwebsite.com/copyleaks/{scanId}/completed
  • yourwebsite.com/copyleaks/{scanId}/source
  • yourwebsite.com/copyleaks/{scanId}/results/{resultId}
  • yourwebsite.com/copyleaks/{scanId}/pdf

Provide the data with CopyleaksService after downloading it from your server.

@Component({
  // ...
})
export class SomeComponent {
  constructor(private copyleaksService: CopyleaksService, private http: HttpClient) {
    const scanId = "some-scan-id";
    // download the source
    // TODO:
    // USE YOUR SOURCE ENDPOINT
    http
      .get<ScanSource>(`/copyleaks/${scanId}/source`)
      .subscribe(source => copyleaksService.pushDownloadedSource(source));

    // download the complete result
    // TODO:
    // USE YOUR COMPLETE RESULT ENDPOINT
    http.get<CompleteResult>(`/copyleaks/${scanId}/complete`).subscribe(completeResult => {
      copyleaksService.pushCompletedResult(completeResult);
      // download each scan result
      // TODO:
      // USE YOUR RESULT ENDPOINT
      const { internet, database, batch } = completeResult.results;
      for (const result of internet) {
        http
          .get<ScanResult>(`/copyleaks/${scanId}/results/${result.id}`)
          .subscribe(scanResult => copyleaksService.pushScanResult(result.id, scanResult));
      }

      // TODO:
      // USE YOUR RESULT ENDPOINT
      for (const result of database) {
        http
          .get<ScanResult>(`/copyleaks/${scanId}/results/${result.id}`)
          .subscribe(scanResult => copyleaksService.pushScanResult(result.id, scanResult));
      }
      // TODO:
      // USE YOUR RESULT ENDPOINT
      for (const result of batch) {
        http
          .get<ScanResult>(`/copyleaks/${scanId}/results/${result.id}`)
          .subscribe(scanResult => copyleaksService.pushScanResult(result.id, scanResult));
      }
    });
  }
}

Progress (optional)

While you are downloading the results for the report component, you can display a percentage indicating your progress in doing so.

@Component({
  // ...
})
export class SomeComponent {
  constructor(private copyleaksService: CopyleaksService, private http: HttpClient) {
    let downloadedResults = 0;
    let totalResults = 0;
    const scanId = "some-scan-id";

    // download the source
    // TODO:
    // USE YOUR SOURCE ENDPOINT
    http
      .get<ScanSource>(`/copyleaks/${scanId}/source`)
      .subscribe(source => copyleaksService.pushDownloadedSource(source));

    // download the complete result
    // TODO:
    // USE YOUR COMPLETE RESULT ENDPOINT
    http.get<CompleteResult>(`/copyleaks/${scanId}/complete`).subscribe(completeResult => {
      copyleaksService.pushCompletedResult(completeResult);

      // download each scan result
      const { internet, database, batch } = completeResult.results;
      totalResults = internet.length + database.length + batch.length;

      // TODO:
      // USE YOUR RESULT ENDPOINT
      for (const result of internet) {
        http.get<ScanResult>(`/copyleaks/${scanId}/results/${result.id}`).subscribe(scanResult => {
          copyleaksService.pushScanResult(result.id, scanResult);
          copyleaksService.setProgress((++downloadedResults / totalResults) * 100);
        });
      }
      // TODO:
      // USE YOUR RESULT ENDPOINT
      for (const result of database) {
        http.get<ScanResult>(`/copyleaks/${scanId}/results/${result.id}`).subscribe(scanResult => {
          copyleaksService.pushScanResult(result.id, scanResult);
          copyleaksService.setProgress((++downloadedResults / totalResults) * 100);
        });
      }
      // TODO:
      // USE YOUR RESULT ENDPOINT
      for (const result of batch) {
        http.get<ScanResult>(`/copyleaks/${scanId}/results/${result.id}`).subscribe(scanResult => {
          copyleaksService.pushScanResult(result.id, scanResult);
          copyleaksService.setProgress((++downloadedResults / totalResults) * 100);
        });
      }
    });
  }
}

Real-Time usage

Note: This method is optional and more advanced

Copyleaks' scan process could take a few seconds if there are a lot of results. It is possible to push the API results as they arrive to your server from Copyleaks API. This can be achieved with web sockets. Copyleaks API can utilize the New Result Webhook every time a single result is ready. This will basically display the result on the results list while it is fetching the actual content of the result.

Note: The New Result Webhook sends only a preview of the actual result. You must download the actual result, and pass it to CopyleaksService

In general it should flow like this:

  1. Use Copyleaks API to scan for plagiarism while providing the relevant webhook configuration.
  2. Once a New Result Webhook arrived on your server, publish it to the relevant web socket connections.
  3. Push the new result data to CopyleaksService and start downloading the actual result

Push NewResult:

Note: This is just an rough example , the implementation of newResultsListener(scanId) is under your responsibility

@Component({
  // ...
})
export class SomeComponent {
  constructor(private copyleaksService: CopyleaksService, private http: HttpClient) {
    const scanId = "some-scan-id";

    // listen to incoming new results
    newResultsListener(scanId).subscribe(newResult => {
      // push the new result to the report
      copyleaksService.pushNewResult(newResult);

      // one of them must contain the result preview.
      const result = newResult.internet[0] || newResult.batch[0] || newResult.database[0];

      // download and push the actual scan result
      http
        .get<ScanResult>(`/copyleaks/${scanId}/results/${result.id}`)
        .subscribe(scanResult => copyleaksService.pushScanResult(result.id, scanResult));
    });
  }
}

Configuration

It is possible to configure the behavior, and the look and state of the report by providing a config via the following methods:

Via component input property:

Note: You can pass the complete config or only a portion of it to the config input property

<!-- some.component.html -->
<cr-copyleaks-report [config]="config"> </cr-copyleaks-report>
// some.component.ts
@Component({
  // ...
})
export class SomeComponent {
  //default config
  public config: CopyleaksReportConfig = {
    contentMode: "html",
    download: false,
    help: false,
    disableSuspectBackButton: false,
    options: {
      showPageSources: false,
      showOnlyTopResults: true,
      showRelated: true,
      showIdentical: true,
      showMinorChanges: true,
      setAsDefault: false
    },
    scanId: null,
    share: false,
    sourcePage: 1,
    suspectId: null,
    suspectPage: 1,
    viewMode: "one-to-many"
  };
}

Via CopyleaksService:

Note: You can pass the complete config or only a portion of it to the setConfig() method

// some.component.ts
@Component({
  // ...
})
export class SomeComponent {
  // plagiarism report will be shown as html
  showHtml() {
    copyleaksService.setConfig({ contentMode: "html" });
  }
  //...
}

Interaction

The component exposes the following events:

name $event description
help MouseEvent emits when the user clicks the help button
share MouseEvent emits when the user clicks the share button
download MouseEvent emits when the user clicks the download button
configChange CopyleaksReportConfig emits when the config is changed

You can use it like so:

<cr-copyleaks-report
  (configChange)="onConfigChange($event)"
  (help)="onHelpBtnClick($event)"
  (share)="onShareBtnClick($event)"
  (download)="onDownloadBtnClick($event)"
></cr-copyleaks-report>

FAQ

My website is not using Angular 8, can I use this component?

No, this component is supported by Angular v8.x. As an alternative you can create an Angular web application that uses this library, and include it in your website using routing. This solution should work without any framework or with other web framework/libraries such as React, AngularJs.

Can I modify this component for my own usage?

Modifying the component is allowed according to the License.

You can’t perform that action at this time.