Monday, October 14, 2019

Redmine Installation on Ubuntu 19.04

Reference:
https://www.hiroom2.com/2019/06/17/ubuntu-1904-redmine-en/

File: redmineInstall.sh
#!/bin/sh -e

MYSQL_VERSION=5.7
[ -z "${MYSQL_PASSWD}" ] && MYSQL_PASSWD=mysql
[ -z "${REDMINE_PASSWD}" ] && REDMINE_PASSWD=redmine

mysql_install()
{
  cat <<EOF | sudo debconf-set-selections
mysql-server-${MYSQL_VERSION} mysql-server/root_password password \
${MYSQL_PASSWD}
mysql-server-${MYSQL_VERSION} mysql-server/root_password_again password \
${MYSQL_PASSWD}
EOF
  sudo apt install -y mysql-server
}

redmine_install()
{
  cat <<EOF | sudo debconf-set-selections
redmine redmine/instances/default/dbconfig-install boolean true
redmine redmine/instances/default/database-type select mysql
redmine redmine/instances/default/mysql/admin-pass password ${MYSQL_PASSWD}
redmine redmine/instances/default/password-confirm password ${MYSQL_PASSWD}
redmine redmine/instances/default/mysql/app-pass password ${REDMINE_PASSWD}
redmine redmine/instances/default/app-password-confirm password \
${REDMINE_PASSWD}
EOF
  sudo apt install -y redmine-mysql
}

apache_install()
{
  sudo apt install -y apache2 libapache2-mod-passenger bundler

  # Overwrite passenger.conf.
  cat << EOF | sudo tee /etc/apache2/mods-available/passenger.conf
<IfModule mod_passenger.c>
  PassengerRoot /usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini
  PassengerDefaultRuby /usr/bin/ruby
  PassengerDefaultUser www-data
  RailsBaseURI /redmine
</IfModule>
EOF

  cd /var/www/html
  sudo ln -s /usr/share/redmine/public redmine
  sudo chown -R www-data:www-data /usr/share/redmine
  cat << EOF | sudo tee /etc/apache2/sites-available/redmine.conf
<VirtualHost _default_:443>
  SSLEngine on
  SSLCertificateFile    /etc/ssl/certs/ssl-cert-snakeoil.pem
  SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key

  <Directory /redmine>
    Options FollowSymLinks
    PassengerResolveSymlinksInDocumentRoot on
    AllowOverride None
  </Directory>
</VirtualHost>
EOF

  sudo a2enmod passenger
  sudo a2enmod ssl
  sudo a2ensite redmine

  sudo systemctl enable apache2
  sudo systemctl restart apache2
}

redmine_main()
{
  mysql_install
  redmine_install
  apache_install
}

redmine_main


To access 

http://server_ip/redmine

Wednesday, October 9, 2019

QR Code with Text Overlay

Prequisite:
sudo apt install python-pip
sudo pip install image
sudo pip install qrcode
sudo pip install fonts
sudo apt-get install ttf-mscorefonts-installer

To test using imagemagick
sudo apt install imagemagick


Python code: test.py
from PIL import Image, ImageDraw,ImageFont
import qrcode

qr = qrcode.QRCode(
version=3,
error_correction=qrcode.constants.ERROR_CORRECT_Q,
box_size=10,
border=4,
)

image = Image.new( "RGBA", ( 410, 480 ) ,"white");

qr.add_data('https://example.com/stuff/rack/1')
qr.make(fit=True)

img = qr.make_image()
print img.size
image.paste(img, (0,0), img.convert("RGBA") );


draw = ImageDraw.Draw(image)
font = ImageFont.truetype("/usr/lib/cinelerra/fonts/arial.ttf",60)
#font = ImageFont.load_default()
txt = "rack 1"
draw.text((100, 410), txt, (0,0,0), font=font)


image.save("qr.png")


To run:
python test.py
display qr.png

Friday, September 13, 2019

Compare two files


MAKE sure you sort the files first
sort file_unsorted > file1
sort file_unsorted2 > file2
The comm command (short for "common") may be useful comm - compare two sorted files line by line
#find lines only in file1
comm -23 file1 file2 

#find lines only in file2
comm -13 file1 file2 

#find lines common to both files
comm -12 file1 file2 

Wednesday, August 14, 2019

Delegation Domain Name

Let's say you need to redirect a website within your domain to an external host.  Instead of creating a webserver and redirecting the traffic.  In some case such as being on the same domain and wanting to redirect to an external name yet it includes your domain.

example: your domain is example.com.  You want www.example.com yet it is hosted by somewhereelse.com.  somewhereelse.com has a c-name of www.example.com

Solution is to add a delegation under your forward lookup zone.  Add two new name server: resolver1.opendns.com and resolver2.opendns.com


Ubuntu Flush DNS

sudo systemd-resolve --flush-caches
sudo systemd-resolve --statistics

Wednesday, July 17, 2019

NGINX PHP-FPM (FastCGI) 504 Gateway Timeout error on


Increase PHP maximum execution time in /etc/php.ini:
  • max_execution_time = 300

  • Increase PHP-FPM request terminate timeout in the pool configuration (/etc/php/7.2/fpm/pool.d/www.conf): 
  • request_terminate_timeout = 300

  • Increase Nginx FastCGI read timeout  under the http section (/etc/nginx/nginx.conf or /etc/nginx/sites-available/nameofvirtualhost): 
  • fastcgi_read_timeout 300;
  • Wednesday, July 3, 2019

    Screenshot of a website



    PhantomJS Installation

    Install PhantomJS on Ubuntu
    sudo apt-get update
    sudo apt-get install build-essential chrpath libssl-dev libxft-dev
    sudo apt-get install libfreetype6 libfreetype6-dev libfontconfig1 libfontconfig1-dev
    wget https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2
    tar xvjf phantomjs-2.1.1-linux-x86_64.tar.bz2 -C /usr/local/share/
    sudo ln -sf /usr/local/share/phantomjs-2.1.1-linux-x86_64/bin/phantomjs /usr/local/bin
    phantomjs --version
    2.1.1

    mkdir /path/to/screenshot
    cd /path/to/screenshot
    Copy rasterize.js in the directory where you want the resulting screenshot to take place.
    wget https://raw.githubusercontent.com/ariya/phantomjs/master/examples/rasterize.js
    phantomjs --debug=yes --ignore-ssl-errors=true --ssl-protocol=any --web-security=true rasterize.js https://enews.ssis.edu.vn enews.png "400px*300px" .25

    The last variable is the zoom factor of the website.  In this case .25 means 25% of the website in a 400px by 300px thumbnail.

    Tuesday, April 23, 2019

    Sort by Color

    Reference: https://www.dynatable.com/?perPage=50&queries%5Bsearch%5D=2012

    // Our custom sort function
    function rgbSort(a, b, attr, direction) {
    
      // Assuming we've created a separate function
      // to get the average RGB value from an image.
      // (see source for example above for getAverageRGB function)
      var aRgb = getAverageRGB(a.img),
          bRgb = getAverageRGB(b.img),
          aDec = ( aRgb.r << 16 ) + ( aRgb.g << 8 ) + aRgb.b,
          bDec = ( bRgb.r << 16 ) + ( bRgb.g << 8 ) + bRgb.b,
          comparison = aDec - bDec;
    
      return direction > 0 ? comparison : -comparison;
    };
    
    // Wait until images are loaded
    $(window).load(function() {
      $('#sorting-function-example')
    
        // Add our custom sort function to dynatable
        .bind('dynatable:init', function(e, dynatable) {
          dynatable.sorts.functions["rgb"] = rgbSort;
        })
    
        // Initialize dynatable
        .dynatable({
          features: {
            paginate: false,
            search: false,
            recordCount: false
          },
          dataset: {
            // When we sort on the color column,
            // use our custom sort added above.
            sortTypes: {
              color: 'rgbSort'
            }
          },
          readers: {
            color: function(cell, record) {
              var $cell = $(cell);
    
              // Store the average RGB image color value
              // as a decimal in "dec" attribute.
              record['img'] = $cell.find('img').get(0);
    
              // Return the HTML of the cell to be stored
              // as the "color" attribute.
              return $cell.html();
            }
          }
        });
    })

    Monday, April 22, 2019

    MS SQL Find Last Created Object

    select 
       so.namesu.name, so.crdate 
    from 
       sysobjects so 
    join 
       sysusers su on so.uid = su.uid  
    order by 
       so.crdate;


    Thursday, April 4, 2019

    PS 12+ Contact Export

    <!DOCTYPE html>
    <html>
    <!-- start right frame -->
    <head>
        <title>Contacts Export</title>
        <link href="/images/css/screen.css" rel="stylesheet" media="screen">
        <link href="/images/css/print.css" rel="stylesheet" media="print">
    </head>
    <body>
        ~[wc:admin_header_frame_css]

        <!-- breadcrumb start -->
        <a href="/admin/home.html" target="_top">~[text:psx.html.admin_students.unlimitedcontacts.start_page]</a> &gt;
        <a href="home.html?selectstudent=nosearch" target="_top">~[text:psx.html.admin_students.unlimitedcontacts.student_selection]</a> &gt;
        Contacts Export
        <!-- breadcrumb end -->

        ~[wc:admin_navigation_frame_css]

    <!-- start of title and student content -->


    <table width="100%">
    <tr>
    <td background="/images/transparent.gif">

    <!-- title -->
    <h1>Contact Export</h1>
    <!-- title -->

    ~[if.isstudent]
    <!-- don't allow students to view the directory. -->

    <!-- start of content and bounding box -->
    <table>
    <tr>
    <td width="23" background="/images/bond_box_left_edge.gif"><img src="/images/spacer.gif" width="23" height="1"></td>
    <td>
    <table>
    <tr>
    <td>Your account does not allow access to this page.</td>
    </tr>
    </table>
    </td>
    <td width="25" background="/images/bond_box_right_edge.gif"><img src="/images/spacer.gif" width="25" height="1"></td>
    </tr>
    </table>
    <br>
    <!-- end of content of bounding box -->

    [else]

    <form name="searchform" action="ssis_contacts_export.html" method="GET" style="float:left;width:500px">
    <table>
    <tr>
                <td  style="background-color:white;">Filter by Grade Level: </td>
    <td style="background-color:white;">
    <a href="ssis_contact_export.html?grade_level=-2">EC3</a>&nbsp;
    <a href="ssis_contact_export.html?grade_level=-1">EC4</a>&nbsp;
    <a href="ssis_contact_export.html?grade_level=0">K</a>&nbsp;
    <a href="ssis_contact_export.html?grade_level=1">1</a>&nbsp;
    <a href="ssis_contact_export.html?grade_level=2">2</a>&nbsp;
      <a href="ssis_contact_export.html?grade_level=3">3</a>&nbsp;
    <a href="ssis_contact_export.html?grade_level=4">4</a>&nbsp;
    <a href="ssis_contact_export.html?grade_level=5">5</a>&nbsp;
    <a href="ssis_contact_export.html?grade_level=6">6</a>&nbsp;
    <a href="ssis_contact_export.html?grade_level=7">7</a>&nbsp;
    <a href="ssis_contact_export.html?grade_level=8">8</a>&nbsp;
    <a href="ssis_contact_export.html?grade_level=9">9</a>&nbsp;
    <a href="ssis_contact_export.html?grade_level=10">10</a>&nbsp;
    <a href="ssis_contact_export.html?grade_level=11">11</a>&nbsp;
    <a href="ssis_contact_export.html?grade_level=12">12</a>&nbsp;
    <a href="ssis_contact_export.html?grade_level=ALL">ALL</a>&nbsp;
    </td>

    </tr>
    </table>
    </form>

    <input type="button" value="Export as Excel" onclick="saveAsExcel('contactExport', 'contactExport.xls')"/>

    <table id="contactExport" class="grid" style="width:100%">
    <tr>
      <th>ID</th>
      <th>Student Full Name</th>
      <th>Grade</th>
      <th>Email</th>
      <th>Gender</th>
      <th>DOB</th>
      <th>Address</th>
      <th>Home Phone</th>
      <th colspan=12>Emergency Contact Information</th>
    </tr>

    ~[tlist_sql;
    WITH StudentsParents AS (
        SELECT DISTINCT
            DECODE(co.ContactRelationship,'Mother','M','Father','F','Step-Mother','M','Step-Father','F','X') ContactRelationship,
            co.StudentDCID,
            co.ContactLastFirst,
            pp.PhoneNumberasentered,
            e.EmailAddress
        FROM
            PSSIS_STU_Contact_Act_Emerg co
            LEFT JOIN PSSIS_Person_Phone pp on pp.PersonID = co.ContactPersonID AND pp.isPreferred = 1
            LEFT JOIN PSSIS_Person_Email e  on e.PersonID  = co.ContactPersonID AND e.isPrimaryEmailAddress = 1
        WHERE co.FilteredPriorityOrder in (1,2,3)
    )
    SELECT DISTINCT
        s.Student_Number, s.lastfirst,
        DECODE(s.grade_level,0,'K',-2,'EC3',-1,'EC4',TRIM(TO_CHAR(s.grade_level))),
        u.Email,
        '<td>' || s.Gender || '</td>' AS Gender,
        '<td>' || TO_CHAR(s.DOB, 'MM/DD/YYYY') || '</td>' AS DOB,
        '<td>' || s.Street || ',' ||
        u.SSIS_Student_Ward || ', ' || u.SSIS_Student_District || ',' ||
        s.City || '</td>' AS Street,
        '<td>' || s.home_phone || '</td>' as Homephone,
        DECODE(m.ContactLastFirst ,'','',
            '<td class="right bold">Mother</td><td>' || m.ContactLastFirst || '</td>' ||
            /* CHR(58) is a colon. Actual colons break TLIST_SQL. */
            '<td>' || m.PhoneNumberasentered || '</td>' ||
            '<td>' || m.EmailAddress || '</td>') AS Mother,
        DECODE(f.ContactLastFirst ,'','',
            '<td class="right bold">Father</td><td>' || f.ContactLastFirst || '</td>' ||
            /* CHR(58) is a colon. Actual colons break TLIST_SQL. */
            '<td>' || f.PhoneNumberasentered || '</td>' ||
            '<td>' || f.EmailAddress || '</td>') AS Father,
        DECODE(x.ContactLastFirst ,'','',
            '<td class="right bold">Emergency</td><td>' || x.ContactLastFirst || '</td>' ||
            '<td>' || x.PhoneNumberasentered || '</td>' ||
            '<td>' || x.EmailAddress || '</td>') AS Emergency
    FROM
        Students s
        INNER JOIN CC ON s.ID = cc.StudentID
        LEFT JOIN StudentsParents m ON s.DCID = m.StudentDCID AND m.ContactRelationship = 'M'
        LEFT JOIN StudentsParents f ON s.DCID = f.StudentDCID AND f.ContactRelationship = 'F'
        LEFT JOIN StudentsParents x ON s.DCID = x.StudentDCID AND x.ContactRelationship = 'X'
        INNER JOIN U_StudentsUserFields u ON s.DCID = u.StudentsDCID
    WHERE
        s.Enroll_Status = 0
        AND cc.TERMID >= (~(curyearid) * 100) and cc.TERMID < (~(curyearid) * 100 + 100)

    ~[if#1.~(gpv.grade_level)=]
            /* NO Grade level provided. */
            AND S.grade_level LIKE 'zzz'
    [else#1]
        ~[if#2.~(gpv.grade_level)=ALL]
            AND S.grade_level LIKE '%'
        [else#2]
        /* Grade Level provided. . */
        AND s.grade_level = ('~[gpv:grade_level]')
        [/if#2]
    [/if#1]

    ORDER BY
        LOWER(s.LastFirst); ]
        <tr valign="top">
            <td>~(s.Student_Number)</td>
            <td>~(s.lastfirst)</td>
            <td>~(s.grade_level)</td>
            <td>~(s.email)</td>
        ~(GenderRow)
        ~(DOBRow)
        ~(StreetRow)
        ~(HomePhoneRow)
        ~(MotherRow)
        ~(FatherRow)
        ~(EmergencyRow)
        </tr>

    [/tlist_sql]

    </table>
    <!-- end student content -->

    [/if.isstudent]

    </td>
    </tr>
    </table>
    <!-- end of title and student content -->

    <p>NOTE:  In order for the contact's information to show up, either the preferred phone number and primary email must be checked off.</p>


    <!-- JN Export using TableExport.js -->
    <!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script>
    <script type="text/javascript" src="/admin/javascript/xlsx.core.js"></script>
    <script type="text/javascript" src="/admin/javascript/Blob.min.js"></script>
    <script type="text/javascript" src="/admin/javascript/FileSaver.min.js"></script>
    <script type="text/javascript" src="/admin/javascript/tableexport.min.js"></script>-->

    <script type="text/javascript" src="/admin/javascript/saveAsExcel.js"></script>

    <!-- <script type="text/javascript">
    $(document).ready(function() {
    $('#contactExport').tableExport({
    formats: ["csv"],
    bootstrap: true,
    });
    });
    </script>
    -->

    </body>
    </html>

    PS 12+ Contact Export with Employer

    <!DOCTYPE html>
    <html>
    <!-- start right frame -->
    <head>
        <title>Contacts Employer Export</title>
        <link href="/images/css/screen.css" rel="stylesheet" media="screen">
        <link href="/images/css/print.css" rel="stylesheet" media="print">


    </head>
    <body>
        ~[wc:admin_header_frame_css]
       
        <!-- breadcrumb start -->
        <a href="/admin/home.html" target="_top">~[text:psx.html.admin_students.unlimitedcontacts.start_page]</a> &gt;
        <a href="home.html?selectstudent=nosearch" target="_top">~[text:psx.html.admin_students.unlimitedcontacts.student_selection]</a> &gt;
        Contacts Export
        <!-- breadcrumb end -->
       
        ~[wc:admin_navigation_frame_css]

    <!-- start of title and student content -->


    <table width="100%">
    <tr>
    <td background="/images/transparent.gif">

    <!-- title -->
    <h1>Contacts Employer Export</h1>
    <!-- title -->


    <input type="button" value="Export as Excel" onclick="saveAsExcel('contactExport', 'contactExport.xls')"/>

    ~[if.isstudent]
    <!-- don't allow students to view the directory. -->

    <!-- start of content and bounding box -->
    <table>
    <tr>
    <td width="23" background="/images/bond_box_left_edge.gif"><img src="/images/spacer.gif" width="23" height="1"></td>
    <td>
    <table>
    <tr>
    <td>Your account does not allow access to this page.</td>
    </tr>
    </table>
    </td>
    <td width="25" background="/images/bond_box_right_edge.gif"><img src="/images/spacer.gif" width="25" height="1"></td>
    </tr>
    </table>
    <br>
    <!-- end of content of bounding box -->

    [else]

    <table id="contactExport" class="grid" style="width:100%">
    <tr>
      <th>Student Full Name</th>
      <th colspan=10>Contact Information</th>
    </tr>

    ~[tlist_sql;
    WITH StudentsParents AS (
        SELECT DISTINCT
            DECODE(co.ContactRelationship,'Mother','M','Father','F','Step-Mother','M','Step-Father','F','X') ContactRelationship,
            co.StudentDCID,
            co.ContactLastFirst,
            pp.PhoneNumberasentered,
            e.EmailAddress,
            co.Employer
        FROM
            PSSIS_STU_Contact_Act co
            LEFT JOIN PSSIS_Person_Phone pp on pp.PersonID = co.ContactPersonDCID AND pp.isPreferred = 1
            LEFT JOIN PSSIS_Person_Email e  on e.PersonID  = co.ContactPersonDCID AND e.isPrimaryEmailAddress = 1
        WHERE co.Employer is not null
    )
    SELECT DISTINCT
        s.lastfirst,
        DECODE(m.ContactLastFirst ,'','',
            '<td class="right bold">Mother</td><td>' || m.ContactLastFirst || '</td>' ||
            /* CHR(58) is a colon. Actual colons break TLIST_SQL. */
            '<td>' || m.PhoneNumberasentered || '</td>' ||
            '<td>' || m.EmailAddress || '</td>' ||
            '<td>' || m.Employer || '</td>') AS Mother,
        DECODE(f.ContactLastFirst ,'','',
            '<td class="right bold">Father</td><td>' || f.ContactLastFirst || '</td>' ||
            /* CHR(58) is a colon. Actual colons break TLIST_SQL. */
            '<td>' || f.PhoneNumberasentered || '</td>' ||
            '<td>' || f.EmailAddress || '</td>' ||
            '<td>' || f.Employer || '</td>') AS Father
    FROM
        Students s
        LEFT JOIN StudentsParents m ON s.DCID = m.StudentDCID AND m.ContactRelationship = 'M'
        LEFT JOIN StudentsParents f ON s.DCID = f.StudentDCID AND f.ContactRelationship = 'F'
    WHERE
        s.enroll_status in (0,-1)
    ORDER BY
        LOWER(s.lastfirst) ; ]
        <tr valign="top">
        <td>~(s.lastfirst)</td>
        ~(MotherRow)
        ~(FatherRow)
        </tr>

    [/tlist_sql]

    </table>
    <!-- end student content -->

    [/if.isstudent]

    </td>
    </tr>
    </table>
    <!-- end of title and student content -->

    <p>NOTE:  In order for the contact's information to show up, either the preferred phone number and primary email must be checked off.</p>


    <!-- JN Export using TableExport.js -->
    <!-- <script type="text/javascript" src="/admin/javascript/xlsx.core.js"></script>
    <script type="text/javascript" src="/admin/javascript/Blob.min.js"></script>
    <script type="text/javascript" src="/admin/javascript/FileSaver.min.js"></script>
    <script type="text/javascript" src="/admin/javascript/TableExport.min.js"></script>
    <script>
        var FormatsTable = document.getElementById('contactExport');
        new TableExport(FormatsTable, {
            formats: ['xlsx', 'csv']
        });
    </script> -->

    <script type="text/javascript" src="/admin/javascript/saveAsExcel.js"></script>

    </body>
    </html>

    PS 12+ Contact Export of Custom Field

    Here is one use report to identify the school specific ID and color code based on the enroll status.  This has the ability to also export out to an Excel.  Notice the javascript saveAsExcel.js in order for the export feature to work.

    <!DOCTYPE html>
    <html>
    <!-- start right frame -->
    <head>
    <title>Contacts Export SSIS ID</title>
    <link href="/images/css/screen.css" rel="stylesheet" media="screen">
    <link href="/images/css/print.css" rel="stylesheet" media="print">
    </head>
    <body>
    ~[wc:admin_header_frame_css]

    <!-- breadcrumb start -->
    <a href="/admin/home.html" target="_top">~[text:psx.html.admin_students.unlimitedcontacts.start_page]</a> &gt;
    <a href="home.html?selectstudent=nosearch" target="_top">~[text:psx.html.admin_students.unlimitedcontacts.student_selection]</a> &gt;
    Contacts Export
    <!-- breadcrumb end -->

    ~[wc:admin_navigation_frame_css]

    <!-- start of title and student content -->


    <table width="100%">
        <tr>
            <td background="/images/transparent.gif">

    <!-- title -->
    <h1>Contact Export with SSIS ID</h1>
    <!-- title -->
    <span style="float:right">CTRL+F to find </span><input type="button" value="Export as Excel" onclick="saveAsExcel('contactExport', 'contactExport.xls')"/>

    <table id="contactExport" class="grid" style="width:100%">
    <tr>
    <th>ID</th>
    <th>Student Full Name</th>
    <th>Enroll Status</th>
    <th>Grade</th>
    <th colspan=9>Contact Information</th>
    </tr>

    ~[tlist_sql;
    WITH StudentsParents AS (
    SELECT DISTINCT
    DECODE(co.ContactRelationship,'Mother','M','Father','F','Step-Mother','M','Step-Father','F','X') ContactRelationship,
    co.StudentDCID,
    co.ContactLastFirst,
    co.ContactPersonID,
    xp.SSIS_PERSON_ID
    FROM
    PSSIS_STU_Contact_Act_Emerg co
    LEFT JOIN U_DEF_EXT_PERSON xp ON xp.PERSONID = co.CONTACTPERSONID
    )
    SELECT DISTINCT
    s.Student_Number, s.lastfirst, s.Enroll_Status,
    DECODE(s.grade_level,0,'K',-2,'EC3',-1,'EC4',TRIM(TO_CHAR(s.grade_level))),
    DECODE(m.ContactLastFirst ,'','',
    /* CHR(58) is a colon. Actual colons break TLIST_SQL. */
    '<td class="right bold">Mother</td><td><a href="../contacts/edit.html#?contactid=' || m.ContactPersonID || '">' || m.ContactLastFirst || '</a></td>' ||
    '<td>' || m.ssis_person_id || '</td>') AS Mother,
    DECODE(f.ContactLastFirst ,'','',
    '<td class="right bold">Father</td><td><a href="../contacts/edit.html#?contactid=' || f.ContactPersonID || '">' || f.ContactLastFirst || '</a></td>' ||
    '<td>' || f.ssis_person_id || '</td>') AS Father,
    DECODE(x.ContactLastFirst ,'','',
    '<td class="right bold">Other</td><td><a href="../contacts/edit.html#?contactid=' || x.ContactPersonID || '">' || x.ContactLastFirst || '</a></td>' ||
    '<td>' || x.ssis_person_id || '</td>') AS Emergency
    FROM
    Students s
    INNER JOIN CC ON s.ID = cc.StudentID
    LEFT JOIN StudentsParents m ON s.DCID = m.StudentDCID AND m.ContactRelationship = 'M'
    LEFT JOIN StudentsParents f ON s.DCID = f.StudentDCID AND f.ContactRelationship = 'F'
    LEFT JOIN StudentsParents x ON s.DCID = x.StudentDCID AND x.ContactRelationship = 'X'
    INNER JOIN U_StudentsUserFields u ON s.DCID = u.StudentsDCID
    /*WHERE
    s.Enroll_Status = 0
    AND cc.TERMID >= (~(curyearid) * 100) and cc.TERMID < (~(curyearid) * 100 + 100) */
    ORDER BY
    LOWER(s.LastFirst); ]
    <tr valign="top" >
    <td>~(s.Student_Number)</td>
    <td>~(s.lastfirst)</td>
    <td style="color: ~(s.Enroll_Status;t;if.test=0;then=gray;else=orange;) ">
    ~(s.Enroll_Status) </td>
    <td>~(s.grade_level)</td>
    ~(MotherRow)
    ~(FatherRow)
    ~(EmergencyRow)
    </tr>

    [/tlist_sql]

            </table>
        <!-- end student content -->


    <script type="text/javascript" src="/admin/javascript/saveAsExcel.js"></script>


    </body>
    </html>