cancel
Showing results for 
Search instead for 
Did you mean: 
martijn_koops
Community Participant

Create javascript links reflecting availability of assigments

Jump to solution

For a few days I have been trying to create a javascript that fetches json from the api.
Finally I figured out something that works more or less...

The idea is to generate a list of assignments on a course page.
The locked ones will be grey, the unlocked ones will be green.

For now I am just trying to fetch the json fromt he api and show it on a page.
or rather, the text response, since the json file starts witjh while(1) .. and is not correct json

I got it to work but I am not allowed in I think, while tyhe script is called form within the coursesite itself.

The response.text  I get form the fetch() is:

"while(1);{"errors":[{"message":"The specified resource does not exist."}]} "

I am calling the script from within the canvas site.

The fetch_test.html file ( contents below) is placed in the files directory of the course.
In a course page I embedded it in an iframe:

<p>
<iframe style="display: block; margin-left: auto; margin-right: auto;" src="https://xxxx/courses/yyyy/files/XXXX/download" width="100%" height="459" data-api-endpoint="https://xxxx/api/v1/courses/yyyy/files/XXXX" data-api-returntype="File"></iframe>
</p>

 
fetch_test.html:
<html>
    <head>
        <script>
            // first figure out the current course Id of the course where this html files is embedded in an Ifram
              pathRegex = new RegExp('([0-9]+)/?/','g');
              var matches = pathRegex.exec(window.location.pathname);
              
              var courseId = matches[1];
              var urlcanvas = '/api/v1/courses/' + courseId + '/assignments?per_page=100';
         
            // fecth the json list of all assigments: file starts with while(1) , so for hte time being fetch text
            fetch(urlcanvas, {credentials: 'include'})
                .then(response => response.text())
                    .then(function(data){
                        document.getElementById("data").innerHTML = data;
                    })
                .catch(function(err){
                    alert(err);
                });
             // next step will be: list all assignements (in buttons?), per module, ans show with colors which ones are locked
            
            </script>
    </head>
    <body>
        
        <h2 > Show the json of assigments in the actual course</h2>
            
        <p id="data"><p>
            
    </body>
</html>
Labels (3)
0 Kudos
1 Solution

Accepted Solutions

haha, sorry, that could have been phrased so much better. Yup, LTI running from another server is probably the way to go. You will need specific Canvas permissions to be able to configure it for your course.

UCF has a python 2.7 LTI starter template, which I have been able to successfully use. 

https://github.com/ucfopen/lti-template-flask

I'm in the process of migrating that to 3.9 and expanding it for my needs. 

View solution in original post

7 Replies
matthew_buckett
Community Participant

I think what is happening here is that the URL that you are embedding in your iframe is sending back a redirect to a different domain and this means that your fetch request is relative to the different domain. So the URL 

https://xxxx/courses/yyyy/files/XXXX/download

gets redirected to:

https://....canvas-user-content.com/courses/...

and then your fetch request is to this new domain which doesn't have the Canvas API on it:

https://....canvas-user-content.com/api/v1/courses/' + courseId + '/assignments?per_page=100

This approach of putting files in Canvas that talks to the Canvas API is prevented by Instructure because of the security implications. If you have access to the account you can put JavaScript in the theme for an account and that way access the API, but otherwise there's no simple way to write some simple HTML that is stored in Canvas and accesses the Canvas API. I wouldn't really recommend putting JS in your theme to do this though.

Locally we have LTI tools that are written as Single Page Applications (HTML/JS) that talk to Canvas through a special proxy that manages OAuth2 tokens and requests tokens on behalf of users.

jsimon3
Community Participant

So I am seeing a few issues here as far as the fetch call goes:
-  the page does not begin with while (1) that is a chrome thing you will just receive the data
-  I do not see any fetch options that refer to credentials of the user/call
-  as far as your initial problem it should be a bit more easy to grasp once you have some good console info

const courseId = "000001";
const fetchData = `/api/v1/courses/${courseId}/assignments?per_page=100`;
    const options = {
      credentials: "same-origin",
      headers: {
        accept: "application/json",
      },
      timeout: 3000,
    };
    fetch(fetchData, options).then(async (response) => {
      const data = await response.json();
      const res = {
        data: data,
        ok: response.ok,
      };
      if (res.ok) {
          //do some things
          console.info(res);
      }
    });

 

werner_huysman1
Community Participant

Hi,

I think there are 2 problems with your approach:

  1. You try to get the hostname-part of the api url with window.location.pathname, but since there is an iframe and the code is actually in the files (which is on a CDN), the hostname part or the url is substituted by something like XXXXX-XXXX.clusterXXX.canva-user-content.com/ and the API url becomes something like XXXXX-XXXX.clusterXXX.canva-user-content.com/api/v1/etc... You could circumvent this by providing the full API url. But then you will probably bump on the second problem.
  2. Most likely you will meet a CORS error, because the API call is executed from within the browser. I think you will need to proxy your API calls to a backend.
martijn_koops
Community Participant

Thank you all very much for the responses!

 

I understand some of it 😉

 

Being a teacher myself I have no access to the systems. I cannot read the console ( I think..) 

 

I do get the correct api-url: I print it to the window,and when I copy paste it in the address bar I hget the information.
I do not really understand how this is fundamentally different in credentials, than asking javascript  make the call.

Would it be possible for me, as a teacher, to get something like this to work?

Could I add javascript to the theme, with only course designer rights?

I am afraid that htemes are managed by our administration.

 

Is there an easy question I could ask our canvas-technicians to create something like this?

 

All I basically need is links that reflect the status of the assignment... This should be possible? 
Or am I mistaken and should i forget about the whole thing?

Thanks again for your interest in my question

Yours sincerely,

Martijn

The html file seems to be stored on a different server, which is a Canvas CDN and has a different domain name.

From a Canvas perspective, any script running from the CDN is tantamount to a request from a 3rd party/untrusted source, which should be blocked by CORS configuration. For requests to work, the CDN should be whitelisted for CORS requests, which Instructure will never do as it is messy.

Seems like LTI is the way to go. I really need to find some simple LTI code to get our tenant working, 

martijn_koops
Community Participant

Thnaks all for responding.

Maybe the last remark offers a solution.

If I understand what "get pour tenant working" means ...

Could I create an LTI on a separate server and have it communicate with my course?

haha, sorry, that could have been phrased so much better. Yup, LTI running from another server is probably the way to go. You will need specific Canvas permissions to be able to configure it for your course.

UCF has a python 2.7 LTI starter template, which I have been able to successfully use. 

https://github.com/ucfopen/lti-template-flask

I'm in the process of migrating that to 3.9 and expanding it for my needs. 

View solution in original post