czwartek, 14 marca 2013

Powershell a sharepoint

System Windows, podobnie jak system Linux posiada własny odpowiednik konsoli (terminala) administratora, w którym można uruchamiać polecenia oraz skrypty, za pomocą których administrator posiada pełną władzę nad systemem. W systemie Windows, interpreter poleceń wykorzystywany przez konsolę, oraz powiązany z nim język nazywa się Windows_PowerShell.

W teorii "Powershell" zapewnia administratorowi wszystkie dostępne opcje administracyjne, które może on wykonać zarówno z poziomu linii komend, jak i poprzez przygotowane wcześniej skrypty. Pełny i praktyczny poradnik, od czego warto zacząć podczas nauki obsługi "Powershella", można znaleźć jako odpowiedź na jedno z pytań, zamieszczonych na forum stackoverflow.com.

Podczas pisania skryptów, dobrze jest mieć "kolorowanie składni", co zapewni nam Powergui.

Skoro już mamy za sobą wstęp teoretyczny, narzędzie do kolorowania składni (aczkolwiek same skrypty zawsze możemy pisać w notatniku), oraz info, gdzie możemy zdobyć więcej praktycznych informacji o samym PowerShellu możemy przejść do analizowania interesującego nas zagadnienia czyli modyfikacja witryny sharepoint za pomocą skryptu powershell.
Utwórzmy wiec skrypt, który będzie pobierał 3 parametry (adres witryny, nazwę tabeli, nazwę pola), a nast. zmieńmy jedno z jego właściwości, np. wymagalność tego pola.

param
(
      [string] $portalURL = $(Throw "Missing 'portalURL' parameter"), #required parameter
      [string] $listName = $(Throw "Missing 'listName' parameter"), #required parameter
      [string] $fieldName = $(Throw "Missing 'fieldName' parameter") #required parameter
)

#komentarze pisze się z haszem na początku

$web = Get-SPWeb $portalURL;
$list = $web.Lists[$listName];
$field = $list.Fields.GetFieldByInternalName($fieldName);
[bool]$fvalue = $field.Required;

if ($fvalue) {
      $field.Required = 0;
      $field.Update();
      $list.Update();
} else {
      $field.Required = 1;
      $field.Update();
      $list.Update();
}
$web.Dispose();
 Jak widać, skrypt jest bardzo prosty. Na samym początku podajemy parametry, wykorzystywane przez skrypt  oraz określamy ich typ (sekcja 'param'). Nast. pobieramy SpWeba, listę SpList i pole SpField, po czym sprawdzamy jego wartość, a nast. zmieniamy jego wartości i wykonujemy update. Na sam koniec pobranego SPWeb'a musimy disposować. Dla programisty sharepoint ten kod wyda się dziwnie znajomy (tylko delikatnie nieco inna składnia).
To co jest WAŻNE, to aby zapisać skrypt w pliku tekstowym z rozszerzeniem *.ps1.

Wywołanie tego kodu, nast. poprzez: "Start->Microsoft Sharepoint 2010 Products -> Sharepoint 2010 Managment Shell"






A nast. w konsoli odpalamy utworzony przez nas skrypt wg. schematu: .\nazwaSkryptu.ps1 -parametrNr1 "ParametrNr1" -ParametrNr2 "ParametrNr2 -ParametrNr3 "ParametrNr3"

W przypadku większej ilości parametrów, zamiast podawać wszystkie parametry z konsoli, lepiej jest utworzyć osobny plik .csv z parametrami i umieścić go w tym samym katalogu co skrypt, a nast. wczytać jego zawartość wewnątrz skryptu.

P.S. Inny, bardziej zaawansowany przykład wykorzystujący power shell w kontekście sharepointa.






czwartek, 7 marca 2013

Build Version Increment

Jednym z bardzo prostych, a zarazem przydatnych pluginów do Visual Studio jest dostępny za darmo Build version increment. Plug in służy do automatycznego zwięszania nr. wersji znajdującego się w pliku AssemblyInfo.cs.

Ważne, aby w rozwiązaniach typu sharepoint inkrementować tylko i wyłącznie "AssemblyFileVersion" (natomiast "AssemblyVersion" musi pozostać nie zmienione). W przypadku normalnych rozwiązań asp.net wolno nam modyfikować oba parametry.

Po zainstalowaniu plug-ina, uruchamiamy go z opcji dostępnych w Visual Studio. Zakładka "Tools"->"Build Version Increment Settings", a nast. w popupie wybieramy interesujący nas projekt, w którym ustawiamy zasady inkrementowania. Osobiście preferuję ustawić opcję inkrementowania w oparciu o build, a numer rewizji w oparciu o "rok, nr. dnia w roku".
Przykładowe skonfigurowane opcje wyglądają tak:




piątek, 1 marca 2013

Pinterest / Blocksit layout

Jednym z najnowszych "krzyków mody", jest wyświetlanie newsów na stronie internetowej w "pseudo-tabelaryczny" sposób. Jest to sposób, który na pierwszy rzut oka przypomina nieco tabelę, ale nią nie jest, czyli dane ustawione są w kolumny, ale wysokość wierszy jest różna i zależna od ilości contentu (wysokość zdjęcia, ilość i długość komentarzy do zdjęcia itp.). Dodatkowo, resizując stronę (zmniejszając lub zwiększając okno przeglądarki) newsy się przestawiają w swojej "pseudo tabeli". Jako pierwsze (ale mogę się mylić), taki layout graficzny zastosowało na swojej stronie https://pinterest.com/, dlatego nazwałem ten layout "pinterest layout".

Teoretycznie, można by było zalogować się na stronę https://pinterest.com/ i spróbować przekopiować ich layout, ale takie rozwiązanie nie było by ani zbyt grzeczne, ani zbyt moralnie poprawne. Na szczęście dzięki www.google.com udało mi się znaleźć stronę, która zagregowała 'know how", czyli link do wtfdiary.com, na którym jest 6 'know how to do pinterest loyout'.

Mi osobiście najbardziej przypadł do gustu BlocksIt.js dlatego w dalszej części skupię się właśnie na tym rozwiązaniu. Jego zalety:
- to łatwość i prostota obsługi,
- ładny wygląd zewnętrzny,
- przystępny tutorial (zawierający 2 projekty demo)
- licencja  GNU GPL 2.0

Samo rozwiązanie nie jest niczym innym, jak wykorzystaniem biblioteki jQuery oraz dołączeniem do niego odpowiedniego jQuery plugin. Do tego dochodzą nam style CSS (ostylowanie naszego contentu) oraz kilka prostych skrytpów javascript (m.in. wykorzystywanych podczas resizowania strony).

To co potrzebujemy to pobrać najnowszą wersję biblioteki query oraz plik zip z demami blocksit

Moje rozwiązanie, które tutaj przedstawię, w dużej mierze opiera się na demie, które można pobrać z linku powyżej i jest to jedynie dostosowanie tego dema do aplikacji typu .net (asp.net / sharepoint).

Aby wykorzystać 'Blocksit' tworzymy nową stronę .aspx (może to być kontrolka .ascx), następnie do projektu dodajemy odpowiednie pliki:
- jquery-1.9.1.min (najnowsza wersja jquery w dniu 2013-03-01)
- blocksit.min (znajduje się w pliku z demem blocksit  - \blocksit-js\blocksit\demo2)
- style.css (znajduje się w pliku z demem blocksit - \blocksit-js\blocksit\demo2)
- zchpitblocksitdemo.js  (nasz plik ze skryptami, jakie będziemy utuchamiać na stronie)

Standardowo te skrypty były na stronie z demem, ale ja wolałem je przenieść do osobnego pliku .js i wyglądają one następująco:

$(document).ready(function () {
    //vendor script
    $('#header')
    .css({ 'top': -50 })
    .delay(1000)
    .animate({ 'top': 0 }, 800);

    $('#footer')
    .css({ 'bottom': -15 })
    .delay(1000)
    .animate({ 'bottom': 0 }, 800);

    //blocksit define
    $(window).load(function () {
        $('#container').BlocksIt({
            numOfCol: 5,
            offsetX: 8,
            offsetY: 8,
            blockElement: '.grid'
        });
    });

    //window resize
    var currentWidth = 1100;
    $(window).resize(function () {
        var winWidth = $(window).width();
        var conWidth;
        if (winWidth < 660) {
            conWidth = 440;
            col = 2
        } else if (winWidth < 880) {
            conWidth = 660;
            col = 3
        } else if (winWidth < 1100) {
            conWidth = 880;
            col = 4;
        } else {
            conWidth = 1100;
            col = 5;
        }

        if (conWidth != currentWidth) {
            currentWidth = conWidth;
            $('#container').width(conWidth);
            $('#container').BlocksIt({
                numOfCol: col,
                offsetX: 8,
                offsetY: 8
            });
        }
    });
});
 Ok. Przejdźmy zatem do omówienia najważniejszej części, czyli kodu strony .aspx / kontrolki .ascx:

Aby uzyskać ten layout, teoretycznie nie potrzebujemy żadnego 'code behind' i wystarczy nam czysty html, który docelowo powinien wyglądać podobnie jak na stronie z dema, czyli mniej więcej tak:

<link rel="stylesheet" href="/_layouts/style.css" type="text/css" />
<script src="/_layouts/jquery-1.9.1.min.js" type="text/javascript"></script>
<script src="/_layouts/blocksit.min.js" type="text/javascript"></script>
<script src="/_layouts//zchpitblocksitdemo.js" type="text/javascript"></script>
<div id="container">
    <div class="grid">
        <div class="imgholder">
            <img src="http://www.inwebson.com/demo/blocksit-js/demo2/images/img26.jpg" />
        </div>
        <strong>Bridge to Heaven</strong>
        <p>Where is the bridge lead to?</p>
        <div class="meta">by SigitEko</div>
    </div>
    <div class="grid">
        <div class="imgholder">
            <img src="http://www.inwebson.com/demo/blocksit-js/demo2/images/img15.jpg" />
        </div>
        <strong>Autumn</strong>
        <p>The fall of the tree...</p>
        <div class="meta">by Lars van de Goor</div>
    </div>
</div>
Aby jednak uzyskać, w pełni dynamicznie generowany przez nas layout, skorzystamy z kontrolki literala, czyli nasz kod html będzie wyglądał tak:

<link rel="stylesheet" href="/_layouts/style.css" type="text/css" />
<script src="/_layouts/jquery-1.9.1.min.js" type="text/javascript"></script>
<script src="/_layouts/blocksit.min.js" type="text/javascript"></script>
<script src="/_layouts//zchpitblocksitdemo.js" type="text/javascript"></script>

<div id="container">
    <asp:Literal runat="server" ID="ltrGrid" ></asp:Literal>
</div>
W tym przypadku, będziemy potrzebowali stworzyć 'code behind', który w najprostszym możliwym przypadku będzie wyglądał tak:

        protected void Page_Load(object sender, EventArgs e)
        {
            SetLiteralGrid();
        }
        private void SetLiteralGrid()
        {
            StringBuilder sb = new StringBuilder();

            sb.AppendLine("<div class='grid'>");
            sb.AppendLine("<div class='imgholder'>");
            sb.AppendLine("<img src='http://www.inwebson.com/demo/blocksit-js/demo2/images/img27.jpg' />");
            sb.AppendLine("</div>");
            sb.AppendLine("<strong>Sunset Lake</strong>");
            sb.AppendLine("<p>A peaceful sunset view...</p>");
            sb.AppendLine("<div class='meta'>by j osborn</div>");
            sb.AppendLine("</div>");

            ltrGrid.Text = sb.ToString();
        }
 Oczywiście w realnych scenariuszach interesuje nas wypełnienie contentem pełnej strony (a nie tylko pojedyńczego newsa), ale wtedy w 'code behind' wystarczy zwyczajnie wcześniej pobrać potrzebne dane i wrzucić je do StringBuildera za pomocą pętli.