Compare commits
	
		
			42 Commits
		
	
	
		
			1.0.3
			...
			civicrm_ma
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 04f2e8eb28 | |||
| d97b124a79 | |||
| 1ad7a4368d | |||
| f1d93b1719 | |||
| 4aaeac1f07 | |||
| 7220ee6178 | |||
| 3fce3c1a7a | |||
| 5832ee4b12 | |||
| 4983b916c7 | |||
| 665a3690b1 | |||
| 7584dc796e | |||
| 5502122e21 | |||
| b056420f9e | |||
| 0564bec241 | |||
| 186bc4f373 | |||
| 7d9b81b324 | |||
| a50249fe22 | |||
| 9443912519 | |||
| 9c4166e573 | |||
| 39c391e803 | |||
| 33add8fd8f | |||
| 1f3ada29d7 | |||
| 442d758cb4 | |||
| b0a959e2e4 | |||
| bdea07164d | |||
| cf4f1fbd46 | |||
| 81a96fbf34 | |||
| eec8b982eb | |||
| 9ed30e8717 | |||
| f675143d59 | |||
| bbea557322 | |||
| c23bf3f8d9 | |||
| d51f265fd5 | |||
| 4e1d28ece6 | |||
| 96384a91ea | |||
| 43559560e8 | |||
| bc9b85e23b | |||
| bbeff69a10 | |||
| 8293415fbd | |||
| 3c3fe48672 | |||
| f8c9d7bf10 | |||
| 8ad7fd5fed | 
@ -1,28 +1,21 @@
 | 
			
		||||
image: ruby:2.4.2
 | 
			
		||||
image: ruby:2.4
 | 
			
		||||
 | 
			
		||||
stages:
 | 
			
		||||
  - build
 | 
			
		||||
  - deploy
 | 
			
		||||
 | 
			
		||||
build:
 | 
			
		||||
  stage: build
 | 
			
		||||
  before_script:
 | 
			
		||||
    - gem install jekyll
 | 
			
		||||
  script:
 | 
			
		||||
    - jekyll build -d public
 | 
			
		||||
  artifacts:
 | 
			
		||||
    paths:
 | 
			
		||||
      - public
 | 
			
		||||
 | 
			
		||||
deploy:
 | 
			
		||||
  stage: deploy
 | 
			
		||||
  before_script:
 | 
			
		||||
    - apt-get update -y
 | 
			
		||||
    - apt-get -y install rsync
 | 
			
		||||
    - gem install jekyll
 | 
			
		||||
    - eval $(ssh-agent -s)
 | 
			
		||||
  script:
 | 
			
		||||
    - jekyll build -d public
 | 
			
		||||
    - ./bin/deploy
 | 
			
		||||
    - ssh-add <(echo "$SSH_PRIVATE_KEY")
 | 
			
		||||
    - rsync -rvz --delete -e 'ssh -o StrictHostKeyChecking=no' ./public/ "$SERVER_USER"@autonomic.zone:/var/www/autonomic.zone/html/
 | 
			
		||||
  artifacts:
 | 
			
		||||
    paths:
 | 
			
		||||
      - public
 | 
			
		||||
  only:
 | 
			
		||||
    - tags
 | 
			
		||||
    - master
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,7 @@
 | 
			
		||||
# Contributing
 | 
			
		||||
 | 
			
		||||
### Not that these instructions may be out of date. If you find any quirks that aren't described in this file, please make patches.
 | 
			
		||||
 | 
			
		||||
# What Is Jekyll
 | 
			
		||||
 | 
			
		||||
For those unfamiliar with how Jekyll works, check out [jekyll.rb] for all the
 | 
			
		||||
@ -36,6 +38,7 @@ Then you can get your Ruby dependencies installed with:
 | 
			
		||||
 | 
			
		||||
``` bash
 | 
			
		||||
$ gem install jekyll bundler
 | 
			
		||||
$ bundle install
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
# Serve Website
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										46
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								README.md
									
									
									
									
									
								
							@ -2,58 +2,28 @@
 | 
			
		||||
 | 
			
		||||
# autonomic-cooperative.gitlab.io
 | 
			
		||||
 | 
			
		||||
A [Jekyll] based site for the Autonomic Cooperative.
 | 
			
		||||
A [Jekyll] based site for the Autonomic Cooperative. The site is based on the [spectral-jekyll-theme] template.
 | 
			
		||||
 | 
			
		||||
The template is based on the [spectral-jekyll-theme].
 | 
			
		||||
 | 
			
		||||
We use [autonomic.zone] for production and [autonomic-cooperative.gitlab.io] for staging.
 | 
			
		||||
We use [autonomic.zone] for production. We used to use [autonomic-cooperative.gitlab.io] as staging but this isn't really needed anymore.
 | 
			
		||||
 | 
			
		||||
[Jekyll]: https://jekyllrb.com/
 | 
			
		||||
[spectral-jekyll-theme]: https://github.com/andrewbanchich/spectral-jekyll-theme
 | 
			
		||||
[autonomic.zone]: https://autonomic.zone/
 | 
			
		||||
[autonomic-cooperative.gitlab.io]: http://autonomic-cooperative.gitlab.io/
 | 
			
		||||
 | 
			
		||||
# Contribute
 | 
			
		||||
# Make a change
 | 
			
		||||
 | 
			
		||||
Please see [CONTRIBUTING.md] for the juicy details.
 | 
			
		||||
 | 
			
		||||
[CONTRIBUTING.md]: https://gitlab.com/autonomic-cooperative/autonomic-cooperative.gitlab.io/blob/master/CONTRIBUTING.md
 | 
			
		||||
 | 
			
		||||
# Make A New Release
 | 
			
		||||
 | 
			
		||||
Please add a new [change log] entry. This helps us track released changes easily.
 | 
			
		||||
 | 
			
		||||
[change log]: https://gitlab.com/autonomic-cooperative/autonomic-cooperative.gitlab.io/blob/master/CHANGELOG.md
 | 
			
		||||
 | 
			
		||||
Then, [tag a new commit] and send it upstream with:
 | 
			
		||||
 | 
			
		||||
[tag a new commit]: https://git-scm.com/book/en/v2/Git-Basics-Tagging
 | 
			
		||||
[semantic versioning]: http://semver.org/
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
$ COMMIT=$(git rev-parse HEAD)
 | 
			
		||||
$ TAG=6.6.6  # enter your new tag
 | 
			
		||||
$ git tag -a $TAG $COMMIT
 | 
			
		||||
$ git push upstream master --tags
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
You can also use the [Gitlab tags UI] for this.
 | 
			
		||||
 | 
			
		||||
[Gitlab tags UI]: https://gitlab.com/autonomic-cooperative/autonomic-cooperative.gitlab.io/tags
 | 
			
		||||
 | 
			
		||||
Our [deploy] CI stage will push the new site to [the production branch].
 | 
			
		||||
Work on features in branches. If you commit to master, open a merge request from your branch unless it is a tiny change. Our [deploy] CI stage will push any changes on master branch to [autonomic.zone].
 | 
			
		||||
 | 
			
		||||
[deploy]: https://gitlab.com/autonomic-cooperative/autonomic-cooperative.gitlab.io/blob/d16aec42bd2ddd7449f55d9f06b03499cc660b22/.gitlab-ci.yml#L17
 | 
			
		||||
[the production branch]: https://gitlab.com/autonomic-cooperative/autonomic-cooperative.gitlab.io/tree/production
 | 
			
		||||
 | 
			
		||||
Watch the [CI/CD pipeline] to see that it builds successfully.
 | 
			
		||||
 | 
			
		||||
[CI/CD pipeline]: https://gitlab.com/autonomic-cooperative/autonomic-cooperative.gitlab.io/pipelines
 | 
			
		||||
 | 
			
		||||
Then head over to [fullyautomatedluxuryinfrastructure] and run:
 | 
			
		||||
 | 
			
		||||
[fullyautomatedluxuryinfrastructure]: https://gitlab.com/autonomic-cooperative/fullyautomatedluxuryinfrastructure
 | 
			
		||||
# Contribute
 | 
			
		||||
 | 
			
		||||
``` bash
 | 
			
		||||
$ ansible-playbook orgs/autonomic/gitlabpages.yml
 | 
			
		||||
```
 | 
			
		||||
Please see [CONTRIBUTING.md] for the juicy details. It may need to be updated so please submit patches if you discover some quirk!
 | 
			
		||||
 | 
			
		||||
[CONTRIBUTING.md]: https://gitlab.com/autonomic-cooperative/autonomic-cooperative.gitlab.io/blob/master/CONTRIBUTING.md
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										26
									
								
								bin/deploy
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								bin/deploy
									
									
									
									
									
								
							@ -1,26 +0,0 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
GITUSERNAME="autonomicgitlabci"
 | 
			
		||||
GITUSEREMAIL="autonomicgitlabci@nowhere.com"
 | 
			
		||||
DEPLOYSCRIPT="https://github.com/X1011/git-directory-deploy/raw/master/deploy.sh"
 | 
			
		||||
 | 
			
		||||
export GIT_DEPLOY_DIR="public"
 | 
			
		||||
export GIT_DEPLOY_BRANCH="production"
 | 
			
		||||
export GIT_DEPLOY_REPO="git@gitlab.com:autonomic-cooperative/autonomic-cooperative.gitlab.io.git"
 | 
			
		||||
 | 
			
		||||
apt-get update -y
 | 
			
		||||
apt-get install -yqq wget openssh-client
 | 
			
		||||
 | 
			
		||||
wget $DEPLOYSCRIPT && chmod +x deploy.sh
 | 
			
		||||
 | 
			
		||||
git config --global user.email $GITUSEREMAIL
 | 
			
		||||
git config --global user.name  $GITUSERNAME
 | 
			
		||||
 | 
			
		||||
mkdir -p ~/.ssh
 | 
			
		||||
eval "$(ssh-agent -s)"
 | 
			
		||||
ssh-add <(echo "$SSH_PRIVATE_KEY")
 | 
			
		||||
echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config
 | 
			
		||||
 | 
			
		||||
./deploy.sh -m "Git tag: $(git describe --exact-match HEAD)"
 | 
			
		||||
 | 
			
		||||
rm -Rfv .ssh
 | 
			
		||||
@ -6,6 +6,7 @@
 | 
			
		||||
    <div class="image">{% if post.image %}<img src="{% if site.featured-image-source %}{{ post.image | prepend: site.featured-image-source | absolute_url }}{% else %}{{ "" | absolute_url }}/assets/images/{{ post.image }}{% endif %}" alt="" />{% endif %}</div>
 | 
			
		||||
    <div class="content">
 | 
			
		||||
      <h2><a href="{{ post.url | relative_url }}" class="link">{{ post.title }}</a></h2>
 | 
			
		||||
      <p class="h5">{{ post.date | date: '%B %d, %Y' }}</p>
 | 
			
		||||
      <p>{{ post.description }}</p>
 | 
			
		||||
    </div>
 | 
			
		||||
  </section>
 | 
			
		||||
 | 
			
		||||
@ -3,7 +3,7 @@
 | 
			
		||||
  <header class="major">
 | 
			
		||||
    <h2>Get in Touch</h2>
 | 
			
		||||
    <p>Contact us to discuss your project's needs and arrange a consultation.</p>
 | 
			
		||||
    <p><a href="mailto:autonomic-coop@posteo.net">autonomic-coop@posteo.net</a></p>
 | 
			
		||||
    <p><a href="mailto:helo@autonomic.zone">helo@autonomic.zone</a></p>
 | 
			
		||||
    <p>
 | 
			
		||||
      If you use encrypted email, here is our <a href="{{ "/assets/pgp/autonomic-key.asc" | relative_url }}">PGP key</a>.
 | 
			
		||||
      Our key fingerprint is: <br/><code id="fingerprint">82FC 87C5 1A71 902F DC10 2CF5 4F90 D55B B24B 1147</code>
 | 
			
		||||
 | 
			
		||||
@ -14,6 +14,13 @@
 | 
			
		||||
  <ul class="copyright">
 | 
			
		||||
    <li class="icon fa-creative-commons"> {{ site.title }}</li>
 | 
			
		||||
  </ul>
 | 
			
		||||
 | 
			
		||||
  <address>
 | 
			
		||||
      Autonomic Co-operative</br>
 | 
			
		||||
      1539 Pershore Road </br>
 | 
			
		||||
      Stirchley</br>
 | 
			
		||||
      B30 2JH
 | 
			
		||||
  </address>
 | 
			
		||||
</footer>
 | 
			
		||||
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
@ -7,5 +7,4 @@
 | 
			
		||||
  <link rel="stylesheet" href="{{ "/assets/styles/main.css" | relative_url }}" />
 | 
			
		||||
  <!--[if lte IE 8]><link rel="stylesheet" href="{{ "/assets/css/ie8.css" | relative_url }}" /><![endif]-->
 | 
			
		||||
  <!--[if lte IE 9]><link rel="stylesheet" href="{{ "/assets/css/ie9.css" | relative_url }}" /><![endif]-->
 | 
			
		||||
  <!-- hi -->
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										5
									
								
								src/_includes/membership-footer.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/_includes/membership-footer.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
<section class="wrapper style5 special compressed">
 | 
			
		||||
    <a href="https://www.coops.tech/" target="_blank">
 | 
			
		||||
    <img src="/assets/images/Member-of-CoTech-logo-200.png" alt="Member of Co-Tech"/>
 | 
			
		||||
    </a>
 | 
			
		||||
</section>
 | 
			
		||||
@ -30,7 +30,7 @@
 | 
			
		||||
        <h3>Cloud Storage and Collaboration</h3>
 | 
			
		||||
        <p>
 | 
			
		||||
          <a href="https://sandstorm.io/">Sandstorm</a> is a personal "cloud
 | 
			
		||||
          in a box" , designed with the upmost security in mind. It allows you to
 | 
			
		||||
          in a box" , designed with the utmost security in mind. It allows you to
 | 
			
		||||
          deploy apps for file-storage, collaborative document editing,
 | 
			
		||||
          calendars, to-do lists and much more.
 | 
			
		||||
        </p>
 | 
			
		||||
@ -71,7 +71,7 @@
 | 
			
		||||
        <p>
 | 
			
		||||
          A grounded and principled understanding of the cybersecurity domain can ensure
 | 
			
		||||
          your organisation is not liable to any unwanted security threats. We provide
 | 
			
		||||
          structured training.
 | 
			
		||||
          structured training tailored to your threat model.
 | 
			
		||||
        </p>
 | 
			
		||||
      </li>
 | 
			
		||||
    </ul>
 | 
			
		||||
 | 
			
		||||
@ -9,6 +9,7 @@
 | 
			
		||||
  {% include services.html %}
 | 
			
		||||
  {% include contact.html %}
 | 
			
		||||
  {% include footer.html %}
 | 
			
		||||
  {% include membership-footer.html %}
 | 
			
		||||
  {% include foot-scripts.html %}
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
 | 
			
		||||
@ -7,8 +7,8 @@
 | 
			
		||||
 | 
			
		||||
    <div id="main">
 | 
			
		||||
        <header>
 | 
			
		||||
            {% if page.image %} 
 | 
			
		||||
            <div 
 | 
			
		||||
            {% if page.image %}
 | 
			
		||||
            <div
 | 
			
		||||
                class="header-image"
 | 
			
		||||
                style="background-image: url('{% if site.featured-image-source %}{{ page.image | prepend: site.featured-image-source | absolute_url }}{% else %}{{ "" | absolute_url }}/assets/images/{{ page.image }}{% endif %}');"></div>
 | 
			
		||||
            {% endif %}
 | 
			
		||||
@ -35,6 +35,7 @@
 | 
			
		||||
                    {{ item.title }}
 | 
			
		||||
                    {% if item.layout %}</a>{% endif %}
 | 
			
		||||
                    </h2>
 | 
			
		||||
                    <p class="h5">{{ item.date | date: '%B %d, %Y' }}</p>
 | 
			
		||||
                    <p>{{ item.description }}</p>
 | 
			
		||||
                </div>
 | 
			
		||||
            </section>
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
---
 | 
			
		||||
layout: post
 | 
			
		||||
title: Our Founding Principles
 | 
			
		||||
description: Autonomic Co-operative And Our Core Values.
 | 
			
		||||
description: Autonomic Co-operative And Our Core Values
 | 
			
		||||
image: pic01.jpg
 | 
			
		||||
category: values
 | 
			
		||||
date: 2017-10-03
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										129
									
								
								src/_posts/2019-08-30-civicrm-mailing-validation.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								src/_posts/2019-08-30-civicrm-mailing-validation.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,129 @@
 | 
			
		||||
---
 | 
			
		||||
layout: post
 | 
			
		||||
title: CiviCRM AngularJS extension
 | 
			
		||||
description: Adding custom validation to the CiviCRM Mailing form
 | 
			
		||||
image: civicrm_validation_header.jpg
 | 
			
		||||
category: howto
 | 
			
		||||
date: 2019-08-30
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
We support [Campaign Against Arms Trade](https://caat.org.uk), a right-on group
 | 
			
		||||
that works to end the international arms trade, with their technology –
 | 
			
		||||
including CiviCRM](https://civicrm.org/), a popular open source
 | 
			
		||||
"constituent relationship management" platform. 
 | 
			
		||||
 | 
			
		||||
Among other things, CAAT uses CiviCRM's "Mailing" features to send out emails to
 | 
			
		||||
their supporters, and they told us that they're experiencing an annoying bug: if
 | 
			
		||||
a user sends out a mailing with the same name (not subject line, just the
 | 
			
		||||
internal identifier 🙄) as an existing one, it'll cause the CRM to freeze up
 | 
			
		||||
elsewhere.
 | 
			
		||||
 | 
			
		||||
As an added challenge, the mailing features of CiviCRM [now use
 | 
			
		||||
AngularJS](https://docs.civicrm.org/dev/en/latest/framework/angular/) following
 | 
			
		||||
a recent rebuild by the developers, and there aren't many tutorials or examples
 | 
			
		||||
out there to customise it. Luckily, the CiviCRM developer community was
 | 
			
		||||
super-helpful, and we managed to sort out some in-form validation to prevent
 | 
			
		||||
duplicate mailing names for our client… and now for you, too!
 | 
			
		||||
 | 
			
		||||
## Create a new extension
 | 
			
		||||
 | 
			
		||||
Using [`civix`](https://github.com/totten/civix), we set up a new CiviCRM extension for our code:
 | 
			
		||||
 | 
			
		||||
    civix generate:module mailing
 | 
			
		||||
 | 
			
		||||
(We called our extension `mailing`, because our creative director was occupied
 | 
			
		||||
with an Art at the time)
 | 
			
		||||
 | 
			
		||||
Our client sensibly keeps their custom CiviCRM extensions in `git`, so at this
 | 
			
		||||
stage we initialised a repository, added the boilerplate template code, and
 | 
			
		||||
pushed.
 | 
			
		||||
 | 
			
		||||
## Set up the AngularJS hook
 | 
			
		||||
 | 
			
		||||
A function called `mailing_civicrm_alterAngular()`  will get executed whenever
 | 
			
		||||
an AngularJS page loads, and you can use a `ChangeSet` to edit an AngularJS
 | 
			
		||||
template. Because AngularJS templates specify form logic, this also lets you
 | 
			
		||||
change the validation behaviour. Our hook function looks like this:
 | 
			
		||||
 | 
			
		||||
    function mailing_civicrm_alterAngular($angular) {
 | 
			
		||||
      $changeSet = \Civi\Angular\ChangeSet::create('mailing_name_unique')
 | 
			
		||||
        ->alterHtml('~/crmMailing/BlockSummary.html', function(phpQueryObject $doc) {
 | 
			
		||||
          // name validation
 | 
			
		||||
          $doc->find('.crm-group:has([crm-ui-id="subform.mailingName"])')->attr('ng-controller', 'NameValidateCtrl');
 | 
			
		||||
          $doc->find('[crm-ui-id="subform.mailingName"]')->attr('ng-blur', 'validateName(mailing, \'name\')');
 | 
			
		||||
          $doc->find('[crm-ui-id="subform.mailingName"]')->attr('crm-ui-validate', 'isValid');
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
      $angular->add($changeSet);
 | 
			
		||||
 | 
			
		||||
      CRM_Core_Resources::singleton()->addScriptFile('mailing', 'js/disallow-duplicate-names.js');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Setting `crm-ui-validate` to `validateName` directly fired the event _way_ too
 | 
			
		||||
many times, so instead `validateName` is only called when focus leaves the
 | 
			
		||||
field, `ng-blur`, which then sets the `isValid` variable that's checked by
 | 
			
		||||
`crm-ui-validate`.
 | 
			
		||||
 | 
			
		||||
## Create the `validateName` function
 | 
			
		||||
 | 
			
		||||
Then, the code which queries the CiviCRM API to check for mailings with
 | 
			
		||||
duplicate names:
 | 
			
		||||
 | 
			
		||||
    var validating = false;
 | 
			
		||||
    
 | 
			
		||||
    (function(angular, $) {
 | 
			
		||||
      var crmMailing = angular.module('crmMailing');
 | 
			
		||||
    
 | 
			
		||||
      crmMailing.controller('NameValidateCtrl', function($scope) {
 | 
			
		||||
          $scope.isValid = false;
 | 
			
		||||
    
 | 
			
		||||
          $scope.validateName = function(mailing, field) {
 | 
			
		||||
            if (!validating) {
 | 
			
		||||
              validating = true;
 | 
			
		||||
    
 | 
			
		||||
              CRM.api3('Mailing', 'get', {
 | 
			
		||||
                "sequential": 1,
 | 
			
		||||
                "name": mailing[field],
 | 
			
		||||
                "id": {"!=": mailing.id}
 | 
			
		||||
              }).then(function(result) {
 | 
			
		||||
                // do something with result
 | 
			
		||||
                if (result.count > 0 ) {
 | 
			
		||||
                  $scope.isValid = false;
 | 
			
		||||
                  CRM.alert(ts('There is already a mailing with this name; sending this one will crash CiviCRM!'));
 | 
			
		||||
                } else {
 | 
			
		||||
                  $scope.isValid = true;
 | 
			
		||||
                }
 | 
			
		||||
              }, function(error) {
 | 
			
		||||
                // oops
 | 
			
		||||
                console.log(error);
 | 
			
		||||
              });
 | 
			
		||||
    
 | 
			
		||||
              validating = false;
 | 
			
		||||
          }
 | 
			
		||||
        };
 | 
			
		||||
      });
 | 
			
		||||
    })(angular, CRM.$);
 | 
			
		||||
 | 
			
		||||
(saved as `js/disallow-duplicate-names.js`)
 | 
			
		||||
 | 
			
		||||
## Conclusion
 | 
			
		||||
 | 
			
		||||
Activate the extension, e.g. with `cv`
 | 
			
		||||
 | 
			
		||||
     $ cv en mailing
 | 
			
		||||
 | 
			
		||||
Now, open a mailing and try to give it the same name as an existing one – you
 | 
			
		||||
should see the field border turn red, and you'll be prevented from continuing or
 | 
			
		||||
sending the mailing:
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
(As a bonus, the extension also sends a notification to the user using
 | 
			
		||||
`CRM.alert` to explain the error)
 | 
			
		||||
 | 
			
		||||
It does seem like a red border sometimes hangs around the field label even after
 | 
			
		||||
the value is valid again… but apart from that, the feature is working great!
 | 
			
		||||
 | 
			
		||||
Lastly, props to CAAT for being a great member of the CiviCRM community and
 | 
			
		||||
supporting us writing this post to share our work with y'all.
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/2019-08-30_civicrm_validation.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/assets/images/2019-08-30_civicrm_validation.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 2.7 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/2019-08-30_civicrm_validation_header.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/assets/images/2019-08-30_civicrm_validation_header.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 97 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/Member-of-CoTech-logo-200.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/assets/images/Member-of-CoTech-logo-200.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 8.5 KiB  | 
@ -11,54 +11,183 @@ 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
 | 
			
		||||
fG9YVaQqGxeUSQ==
 | 
			
		||||
=OH/1
 | 
			
		||||
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
 | 
			
		||||
AhF2loFrCEnlZw==
 | 
			
		||||
=u0eg
 | 
			
		||||
-----END PGP PUBLIC KEY BLOCK-----
 | 
			
		||||
 | 
			
		||||
@ -107,6 +107,7 @@ h4 {
 | 
			
		||||
h5 {
 | 
			
		||||
  font-size: 0.8em;
 | 
			
		||||
  line-height: 1.5em;
 | 
			
		||||
  font-style: italic;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.h6,
 | 
			
		||||
@ -232,4 +233,4 @@ header {
 | 
			
		||||
      display: none;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -54,7 +54,7 @@
 | 
			
		||||
 | 
			
		||||
      > a {
 | 
			
		||||
        border: 0;
 | 
			
		||||
        color: inherit;
 | 
			
		||||
        color: black;
 | 
			
		||||
        display: block;
 | 
			
		||||
        font-size: 0.8em;
 | 
			
		||||
        letter-spacing: _size(letter-spacing-alt);
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,7 @@
 | 
			
		||||
      color: _palette($p, fg-bold);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    .h2, .h3, .h4, .h5, .h6,
 | 
			
		||||
    h2, h3, h4, h5, h6 {
 | 
			
		||||
      color: _palette($p, fg-bold);
 | 
			
		||||
@ -210,6 +210,14 @@
 | 
			
		||||
    padding: 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &.compressed {
 | 
			
		||||
      padding: 0.5em 0 0;
 | 
			
		||||
 | 
			
		||||
      img {
 | 
			
		||||
          max-width: 150px;
 | 
			
		||||
      }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &.style1 {
 | 
			
		||||
    @include wrapper(accent1);
 | 
			
		||||
  }
 | 
			
		||||
@ -229,7 +237,7 @@
 | 
			
		||||
  &.style5 {
 | 
			
		||||
    @include wrapper(accent2);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  &.style6 {
 | 
			
		||||
    @include wrapper(accent4);
 | 
			
		||||
  }
 | 
			
		||||
@ -241,4 +249,4 @@
 | 
			
		||||
  @include breakpoint(small) {
 | 
			
		||||
    @include padding(3em, 2em);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -50,7 +50,7 @@
 | 
			
		||||
      border2:    rgba(0,0,0,0.25),
 | 
			
		||||
      border2-bg:   rgba(255,255,255,0.2)
 | 
			
		||||
    ),
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    accent2: (
 | 
			
		||||
      bg:       #ffffff,
 | 
			
		||||
      fg-bold:    #2E3842,
 | 
			
		||||
@ -72,7 +72,7 @@
 | 
			
		||||
      border2:    rgba(0,0,0,0.25),
 | 
			
		||||
      border2-bg:   rgba(255,255,255,0.2)
 | 
			
		||||
    ),
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    accent4: (
 | 
			
		||||
      bg:       #25558C,
 | 
			
		||||
      fg-bold:    #ffffff,
 | 
			
		||||
@ -82,5 +82,16 @@
 | 
			
		||||
      border-bg:    rgba(255,255,255,0.075),
 | 
			
		||||
      border2:    rgba(0,0,0,0.25),
 | 
			
		||||
      border2-bg:   rgba(255,255,255,0.2)
 | 
			
		||||
    )
 | 
			
		||||
  );
 | 
			
		||||
    ),
 | 
			
		||||
 | 
			
		||||
    accent5: (
 | 
			
		||||
      bg:       #e2e2e2,
 | 
			
		||||
      fg-bold:    #ffffff,
 | 
			
		||||
      fg:       mix(#F3A712, #ffffff, 25%),
 | 
			
		||||
      fg-light:   mix(#F3A712, #ffffff, 40%),
 | 
			
		||||
      border:     rgba(0,0,0,0.125),
 | 
			
		||||
      border-bg:    rgba(255,255,255,0.075),
 | 
			
		||||
      border2:    rgba(0,0,0,0.25),
 | 
			
		||||
      border2-bg:   rgba(255,255,255,0.2)
 | 
			
		||||
    ),
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
@ -126,15 +126,15 @@ body.is-mobile {
 | 
			
		||||
/* Footer */
 | 
			
		||||
 | 
			
		||||
#footer {
 | 
			
		||||
  @include padding(6em, 0);
 | 
			
		||||
  padding: 4em 0 3.5em;
 | 
			
		||||
  background-color: darken(_palette(bg), 8);
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  color: rgba(255, 255, 255, 0.7);
 | 
			
		||||
 | 
			
		||||
  .icons {
 | 
			
		||||
    font-size: 1.25em;
 | 
			
		||||
 | 
			
		||||
    a {
 | 
			
		||||
      color: _palette(fg-light);
 | 
			
		||||
 | 
			
		||||
      &:hover {
 | 
			
		||||
        color: _palette(fg);
 | 
			
		||||
@ -143,7 +143,6 @@ body.is-mobile {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .copyright {
 | 
			
		||||
    color: _palette(fg-light);
 | 
			
		||||
    font-size: 0.8em;
 | 
			
		||||
    letter-spacing: _size(letter-spacing-alt);
 | 
			
		||||
    list-style: none;
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user